mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Get codebase completely working with LLVM
You can now build Cosmopolitan with Clang: make -j8 MODE=llvm o/llvm/examples/hello.com The assembler and linker code is now friendly to LLVM too. So it's not needed to configure Clang to use binutils under the hood. If you love LLVM then you can now use pure LLVM.
This commit is contained in:
parent
0e36cb3ac4
commit
e75ffde09e
4528 changed files with 7776 additions and 11640 deletions
4
Makefile
4
Makefile
|
@ -117,8 +117,6 @@ include third_party/gdtoa/gdtoa.mk # │ You can finally call malloc()
|
||||||
include libc/time/time.mk # │
|
include libc/time/time.mk # │
|
||||||
include libc/alg/alg.mk # │
|
include libc/alg/alg.mk # │
|
||||||
include libc/stdio/stdio.mk # │
|
include libc/stdio/stdio.mk # │
|
||||||
include third_party/f2c/f2c.mk # │
|
|
||||||
include third_party/blas/blas.mk # │
|
|
||||||
include net/net.mk # │
|
include net/net.mk # │
|
||||||
include libc/log/log.mk # │
|
include libc/log/log.mk # │
|
||||||
include dsp/core/core.mk # │
|
include dsp/core/core.mk # │
|
||||||
|
@ -203,7 +201,7 @@ CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||||
|
|
||||||
bins: $(BINS)
|
bins: $(BINS)
|
||||||
check: $(CHECKS)
|
check: $(CHECKS)
|
||||||
test: $(TESTS)
|
test: $(TESTS) all
|
||||||
depend: o/$(MODE)/depend
|
depend: o/$(MODE)/depend
|
||||||
tags: TAGS HTAGS
|
tags: TAGS HTAGS
|
||||||
|
|
||||||
|
|
43
README.md
43
README.md
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
|
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
|
||||||
a build-once run-anywhere language, like Java, except it doesn't need an
|
a build-once run-anywhere language, like Java, except it doesn't need an
|
||||||
interpreter or virtual machine. Instead, it reconfigures stock GCC to
|
interpreter or virtual machine. Instead, it reconfigures stock GCC and
|
||||||
output a POSIX-approved polyglot format that runs natively on Linux +
|
Clang to output a POSIX-approved polyglot format that runs natively on
|
||||||
Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best possible
|
Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best
|
||||||
performance and the tiniest footprint imaginable.
|
possible performance and the tiniest footprint imaginable.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
|
@ -18,24 +18,33 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
Cosmopolitan can be compiled from source on any Linux distro.
|
If you're doing your development work on Linux or BSD then you need just
|
||||||
|
five files to get started:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-0.1.2.zip
|
||||||
|
unzip cosmopolitan-amalgamated-0.1.2.zip
|
||||||
|
echo 'main() { printf("hello world\n"); }' >hello.c
|
||||||
|
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
|
||||||
|
./hello.com
|
||||||
|
```
|
||||||
|
|
||||||
|
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)
|
||||||
|
tutorial. It's needed because the ELF object format is what makes
|
||||||
|
universal binaries possible.
|
||||||
|
|
||||||
|
Cosmopolitan can also be compiled from source on any Linux distro.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
wget https://justine.lol/cosmopolitan/cosmopolitan-0.1.2.tar.gz
|
||||||
tar xf cosmopolitan-0.1.2.tar.gz # see releases page
|
tar xf cosmopolitan-0.1.2.tar.gz # see releases page
|
||||||
cd cosmopolitan-0.1.2
|
cd cosmopolitan-0.1.2
|
||||||
make -j16
|
make -j16
|
||||||
o//examples/hello.com
|
o//examples/hello.com
|
||||||
find o -name \*.com | xargs ls -rShal | less
|
find o -name \*.com | xargs ls -rShal | less
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively you can use the release binaries:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
unzip cosmopolitan-amalgamated-0.1.2.zip # see releases page
|
|
||||||
echo 'main() { printf("hello world\n"); }' >hello.c
|
|
||||||
gcc -g -O -static -fno-pie -no-pie -mno-red-zone -nostdlib -nostdinc \
|
|
||||||
-o hello.com.dbg hello.c -Wl,--gc-sections -Wl,-z,max-page-size=0x1000 -fuse-ld=bfd \
|
|
||||||
-Wl,-T,ape.lds -include cosmopolitan.h crt.o ape.o cosmopolitan.a
|
|
||||||
objcopy -SO binary hello.com.dbg hello.com
|
|
||||||
./hello.com
|
|
||||||
```
|
|
||||||
|
|
323
ape/ape.lds
323
ape/ape.lds
|
@ -36,7 +36,7 @@
|
||||||
entails two steps: (1) create a .com.dbg binary w/ Linux toolchain and
|
entails two steps: (1) create a .com.dbg binary w/ Linux toolchain and
|
||||||
then (2) unwrap the .com binary embedded within:
|
then (2) unwrap the .com binary embedded within:
|
||||||
|
|
||||||
objcopy -SO binary input.com.dbg output.com
|
objcopy -S -O binary input.com.dbg output.com
|
||||||
|
|
||||||
Both executables will work fine, but only the .com format is portable.
|
Both executables will work fine, but only the .com format is portable.
|
||||||
|
|
||||||
|
@ -182,21 +182,6 @@
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
/* Plans real memory solution at linktime. */
|
|
||||||
MEMORY {
|
|
||||||
PageZero : org = 0x0000000000000000, len = 0x0000000000001000
|
|
||||||
RealBss : org = XLM_BASE_REAL, len = XLM_SIZE
|
|
||||||
RealProgram : org = IMAGE_BASE_REAL, len = 0x0000000000010000 - IMAGE_BASE_REAL
|
|
||||||
RealScratch : org = REAL_SCRATCH_AREA, len = REAL_STACK_FRAME - REAL_SCRATCH_AREA
|
|
||||||
RealStack : org = REAL_STACK_FRAME, len = 0x0000000000010000
|
|
||||||
EbdaMemory : org = 0x0000000000080000, len = 0x0000000000020000
|
|
||||||
VideoMemory : org = 0x00000000000a0000, len = 0x0000000000020000
|
|
||||||
Romz : org = 0x00000000000c0000, len = 0x0000000000030000
|
|
||||||
BiosMemory : org = 0x00000000000f0000, len = 0x0000000000010000
|
|
||||||
SmallCode : org = IMAGE_BASE_PHYSICAL, len = 0x0000000040000000 - IMAGE_BASE_PHYSICAL
|
|
||||||
ZipData : org = 0x0000000040000000, len = 0x0000000040000000
|
|
||||||
}
|
|
||||||
|
|
||||||
PHDRS {
|
PHDRS {
|
||||||
Head PT_LOAD FLAGS(5);
|
Head PT_LOAD FLAGS(5);
|
||||||
Rom PT_LOAD FLAGS(5);
|
Rom PT_LOAD FLAGS(5);
|
||||||
|
@ -221,34 +206,34 @@ SECTIONS {
|
||||||
/* Executable & Linkable Format */
|
/* Executable & Linkable Format */
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
||||||
KEEP(*(.elf.phdrs))
|
KEEP(*(.elf.phdrs))
|
||||||
HIDDEN(.Lape.phdrs.end = .);
|
HIDDEN(ape_phdrs_end = .);
|
||||||
. += 1;
|
. += 1;
|
||||||
|
|
||||||
/* OpenBSD */
|
/* OpenBSD */
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
|
||||||
HIDDEN(.Lape.note = .);
|
HIDDEN(ape_note = .);
|
||||||
KEEP(*(.note.openbsd.ident))
|
KEEP(*(.note.openbsd.ident))
|
||||||
KEEP(*(.note.netbsd.ident))
|
KEEP(*(.note.netbsd.ident))
|
||||||
HIDDEN(.Lape.note.end = .);
|
HIDDEN(ape_note_end = .);
|
||||||
. += 1;
|
. += 1;
|
||||||
|
|
||||||
/* Portable Executable */
|
/* Portable Executable */
|
||||||
KEEP(*(.pe.header))
|
KEEP(*(.pe.header))
|
||||||
HIDDEN(.Lape.pe.sections = .);
|
HIDDEN(ape_pe_sections = .);
|
||||||
KEEP(*(.pe.sections))
|
KEEP(*(.pe.sections))
|
||||||
HIDDEN(.Lape.pe.sections_end = .);
|
HIDDEN(ape_pe_sections_end = .);
|
||||||
. += 1;
|
. += 1;
|
||||||
|
|
||||||
/* Mach-O */
|
/* Mach-O */
|
||||||
KEEP(*(.macho))
|
KEEP(*(.macho))
|
||||||
. = ALIGN(__SIZEOF_POINTER__);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
HIDDEN(.Lape.macho.end = .);
|
HIDDEN(ape_macho_end = .);
|
||||||
. += 1;
|
. += 1;
|
||||||
|
|
||||||
KEEP(*(.ape.pad.head))
|
KEEP(*(.ape.pad.head))
|
||||||
. = ALIGN(SupportsWindows() ? PAGESIZE : 16);
|
. = ALIGN(SupportsWindows() ? PAGESIZE : 16);
|
||||||
HIDDEN(_ehead = .);
|
HIDDEN(_ehead = .);
|
||||||
} AT>SmallCode :Head
|
} :Head
|
||||||
|
|
||||||
/*BEGIN: nt addressability guarantee */
|
/*BEGIN: nt addressability guarantee */
|
||||||
|
|
||||||
|
@ -266,7 +251,7 @@ SECTIONS {
|
||||||
*(.start)
|
*(.start)
|
||||||
KEEP(*(.initprologue))
|
KEEP(*(.initprologue))
|
||||||
KEEP(*(SORT_BY_NAME(.init.*)))
|
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||||
KEEP(*(SORT_NONE(.init)))
|
KEEP(*(.init))
|
||||||
KEEP(*(.initepilogue))
|
KEEP(*(.initepilogue))
|
||||||
KEEP(*(.pltprologue))
|
KEEP(*(.pltprologue))
|
||||||
*(.plt)
|
*(.plt)
|
||||||
|
@ -290,19 +275,13 @@ SECTIONS {
|
||||||
*(.text .stub .text.*)
|
*(.text .stub .text.*)
|
||||||
KEEP(*(SORT_BY_NAME(.sort.text.*)))
|
KEEP(*(SORT_BY_NAME(.sort.text.*)))
|
||||||
|
|
||||||
/* Won't support NX bit DRM for tiny executables */
|
|
||||||
HIDDEN(.Lape.piro.align = ABSOLUTE(. > APE_PIRO_THRESHOLD ? 0x1000 : 8));
|
|
||||||
|
|
||||||
/* Code that musn't be mapped in production */
|
|
||||||
KEEP(*(.ape.pad.test));
|
KEEP(*(.ape.pad.test));
|
||||||
. = ALIGN(.Lape.piro.align);
|
|
||||||
HIDDEN(__test_start = .);
|
HIDDEN(__test_start = .);
|
||||||
*(.test.unlikely)
|
*(.test.unlikely)
|
||||||
*(.test .test.*)
|
*(.test .test.*)
|
||||||
|
|
||||||
/* Privileged code invulnerable to magic */
|
/* Privileged code invulnerable to magic */
|
||||||
KEEP(*(.ape.pad.privileged));
|
KEEP(*(.ape.pad.privileged));
|
||||||
. = ALIGN(.Lape.piro.align);
|
|
||||||
HIDDEN(__privileged_start = .);
|
HIDDEN(__privileged_start = .);
|
||||||
HIDDEN(__test_end = .);
|
HIDDEN(__test_end = .);
|
||||||
. += 1;
|
. += 1;
|
||||||
|
@ -312,23 +291,10 @@ SECTIONS {
|
||||||
/*BEGIN: Read Only Data */
|
/*BEGIN: Read Only Data */
|
||||||
|
|
||||||
KEEP(*(.ape.pad.rodata));
|
KEEP(*(.ape.pad.rodata));
|
||||||
. = ALIGN(.Lape.piro.align);
|
|
||||||
. += 1;
|
|
||||||
|
|
||||||
/* Nonspecific Read-Only Data */
|
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
. += 1;
|
|
||||||
|
|
||||||
/* Undefined Behavior Sanitizer Types */
|
|
||||||
HIDDEN(__ubsan_types_start = .);
|
|
||||||
*(.ubsan.types)
|
*(.ubsan.types)
|
||||||
HIDDEN(__ubsan_types_end = .);
|
|
||||||
. += 1;
|
|
||||||
|
|
||||||
/* Undefined Behavior Sanitizer Data */
|
|
||||||
HIDDEN(__ubsan_data_start = .);
|
|
||||||
*(.ubsan.data)
|
*(.ubsan.data)
|
||||||
HIDDEN(__ubsan_data_end = .);
|
|
||||||
|
|
||||||
/* Unit Test & Fixture Registry */
|
/* Unit Test & Fixture Registry */
|
||||||
|
|
||||||
|
@ -340,7 +306,7 @@ SECTIONS {
|
||||||
KEEP(*(.comment))
|
KEEP(*(.comment))
|
||||||
KEEP(*(.commentepilogue))
|
KEEP(*(.commentepilogue))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Windows DLL Import Directory */
|
/* Windows DLL Import Directory */
|
||||||
KEEP(*(.idata.ro));
|
KEEP(*(.idata.ro));
|
||||||
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
||||||
|
@ -350,16 +316,16 @@ SECTIONS {
|
||||||
PROVIDE_HIDDEN(__init_array_start = .);
|
PROVIDE_HIDDEN(__init_array_start = .);
|
||||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
KEEP(*(SORT_NONE(.ctors)))
|
KEEP(*(.ctors))
|
||||||
KEEP(*(SORT_NONE(.init_array)))
|
KEEP(*(.init_array))
|
||||||
KEEP(*(SORT_NONE(.preinit_array)))
|
KEEP(*(.preinit_array))
|
||||||
PROVIDE_HIDDEN(__init_array_end = .);
|
PROVIDE_HIDDEN(__init_array_end = .);
|
||||||
|
|
||||||
. = ALIGN(__SIZEOF_POINTER__);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||||
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
KEEP(*(SORT_NONE(.dtors)))
|
KEEP(*(.dtors))
|
||||||
PROVIDE_HIDDEN(__fini_array_end = .);
|
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||||
|
|
||||||
/* Encoded Data Structures w/ Linear Initialization Order */
|
/* Encoded Data Structures w/ Linear Initialization Order */
|
||||||
|
@ -369,13 +335,12 @@ SECTIONS {
|
||||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||||
|
|
||||||
KEEP(*(.ape.pad.text))
|
KEEP(*(.ape.pad.text))
|
||||||
HIDDEN(.Lape.data.align = ABSOLUTE(PAGESIZE));
|
. = ALIGN(PAGESIZE);
|
||||||
. = ALIGN(.Lape.data.align);
|
|
||||||
HIDDEN(_etext = .);
|
HIDDEN(_etext = .);
|
||||||
PROVIDE_HIDDEN(etext = .);
|
PROVIDE_HIDDEN(etext = .);
|
||||||
/*END: Read Only Data (only needed for initialization) */
|
/*END: Read Only Data (only needed for initialization) */
|
||||||
/*END: Read Only Data */
|
/*END: Read Only Data */
|
||||||
} AT>SmallCode :Rom
|
} :Rom
|
||||||
|
|
||||||
.data . : {
|
.data . : {
|
||||||
/*BEGIN: Read/Write Data */
|
/*BEGIN: Read/Write Data */
|
||||||
|
@ -393,24 +358,21 @@ SECTIONS {
|
||||||
KEEP(*(.gotpltepilogue))
|
KEEP(*(.gotpltepilogue))
|
||||||
|
|
||||||
/*BEGIN: Post-Initialization Read-Only */
|
/*BEGIN: Post-Initialization Read-Only */
|
||||||
. = ALIGN(.Lape.piro.align);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
HIDDEN(__piro_start = .);
|
|
||||||
|
|
||||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||||
PROVIDE_HIDDEN(__relo_end = .);
|
PROVIDE_HIDDEN(__relo_end = .);
|
||||||
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||||
KEEP(*(.piro.pad.data))
|
KEEP(*(.piro.pad.data))
|
||||||
. = ALIGN(.Lape.data.align);
|
. = ALIGN(PAGESIZE);
|
||||||
HIDDEN(_edata = .);
|
HIDDEN(_edata = .);
|
||||||
PROVIDE_HIDDEN(edata = .);
|
PROVIDE_HIDDEN(edata = .);
|
||||||
} AT>SmallCode :Ram
|
} :Ram
|
||||||
|
|
||||||
.bss . : {
|
.bss . : {
|
||||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||||
*(.piro.bss)
|
*(.piro.bss)
|
||||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||||
. += 1;
|
|
||||||
. = ALIGN(.Lape.piro.align);
|
|
||||||
HIDDEN(__piro_end = .);
|
HIDDEN(__piro_end = .);
|
||||||
/*END: Post-Initialization Read-Only */
|
/*END: Post-Initialization Read-Only */
|
||||||
|
|
||||||
|
@ -429,13 +391,16 @@ SECTIONS {
|
||||||
. = ALIGN(0x10000); /* for brk()/sbrk() allocation */
|
. = ALIGN(0x10000); /* for brk()/sbrk() allocation */
|
||||||
HIDDEN(_end = .);
|
HIDDEN(_end = .);
|
||||||
PROVIDE_HIDDEN(end = .);
|
PROVIDE_HIDDEN(end = .);
|
||||||
} AT>SmallCode :Ram
|
} :Ram
|
||||||
|
|
||||||
/*END: nt addressability guarantee */
|
/*END: nt addressability guarantee */
|
||||||
/*END: bsd addressability guarantee */
|
/*END: bsd addressability guarantee */
|
||||||
/*END: linux addressability guarantee */
|
/*END: linux addressability guarantee */
|
||||||
/*END: xnu addressability guarantee */
|
/*END: xnu addressability guarantee */
|
||||||
|
|
||||||
|
.shstrtab : { *(.shstrtab) }
|
||||||
|
.strtab : { *(.strtab) }
|
||||||
|
.symtab : { *(.symtab) }
|
||||||
.stab 0 : { *(.stab) }
|
.stab 0 : { *(.stab) }
|
||||||
.stabstr 0 : { *(.stabstr) }
|
.stabstr 0 : { *(.stabstr) }
|
||||||
.stab.excl 0 : { *(.stab.excl) }
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
@ -468,80 +433,81 @@ SECTIONS {
|
||||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||||
|
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
|
*(__mcount_loc)
|
||||||
*(.discard)
|
*(.discard)
|
||||||
*(.yoink)
|
*(.yoink)
|
||||||
*(.*)
|
*(.*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PFSTUB8(.Lape.elf.entry, _start);
|
PFSTUB8(ape_elf_entry, _start);
|
||||||
PFSTUB8(.Lape.elf.phoff, RVA(ape.phdrs));
|
PFSTUB8(ape_elf_phoff, RVA(ape_phdrs));
|
||||||
PFSTUB8(.Lape.elf.shoff, 0);
|
PFSTUB8(ape_elf_shoff, 0);
|
||||||
PFSTUB4(.Lape.elf.phnum, (.Lape.phdrs.end - ape.phdrs) / 56);
|
PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
|
||||||
PFSTUB4(.Lape.elf.shnum, 0);
|
PFSTUB4(ape_elf_shnum, 0);
|
||||||
PFSTUB4(.Lape.elf.shstrndx, 0);
|
PFSTUB4(ape_elf_shstrndx, 0);
|
||||||
|
|
||||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||||
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
|
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
|
||||||
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
||||||
|
|
||||||
HIDDEN(.Lape.rom.offset = 0);
|
HIDDEN(ape_rom_offset = 0);
|
||||||
HIDDEN(.Lape.rom.vaddr = ADDR(.head));
|
HIDDEN(ape_rom_vaddr = ADDR(.head));
|
||||||
HIDDEN(.Lape.rom.paddr = LOADADDR(.head));
|
HIDDEN(ape_rom_paddr = LOADADDR(.head));
|
||||||
HIDDEN(.Lape.rom.filesz = LOADADDR(.data) - .Lape.rom.paddr);
|
HIDDEN(ape_rom_filesz = LOADADDR(.data) - ape_rom_paddr);
|
||||||
HIDDEN(.Lape.rom.memsz = ADDR(.data) - ADDR(.head));
|
HIDDEN(ape_rom_memsz = ADDR(.data) - ADDR(.head));
|
||||||
HIDDEN(.Lape.rom.align = .Lape.data.align);
|
HIDDEN(ape_rom_align = PAGESIZE);
|
||||||
HIDDEN(.Lape.rom.rva = RVA(.Lape.rom.vaddr));
|
HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
|
||||||
|
|
||||||
HIDDEN(.Lape.ram.offset = .Lape.rom.offset + .Lape.rom.filesz);
|
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
|
||||||
HIDDEN(.Lape.ram.vaddr = ADDR(.data));
|
HIDDEN(ape_ram_vaddr = ADDR(.data));
|
||||||
HIDDEN(.Lape.ram.paddr = LOADADDR(.data));
|
HIDDEN(ape_ram_paddr = LOADADDR(.data));
|
||||||
HIDDEN(.Lape.ram.filesz = LOADADDR(.bss) - LOADADDR(.data));
|
HIDDEN(ape_ram_filesz = LOADADDR(.bss) - LOADADDR(.data));
|
||||||
HIDDEN(.Lape.ram.memsz = ADDR(.bss) + SIZEOF(.bss) - .Lape.ram.vaddr);
|
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
|
||||||
HIDDEN(.Lape.ram.align = .Lape.data.align);
|
HIDDEN(ape_ram_align = PAGESIZE);
|
||||||
HIDDEN(.Lape.ram.rva = RVA(.Lape.ram.vaddr));
|
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||||
|
|
||||||
HIDDEN(.Lape.note.offset = .Lape.rom.offset + (.Lape.note - .Lape.rom.vaddr));
|
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
|
||||||
HIDDEN(.Lape.note.vaddr = .Lape.note);
|
HIDDEN(ape_note_vaddr = ape_note);
|
||||||
HIDDEN(.Lape.note.paddr = .Lape.rom.paddr + .Lape.note.offset);
|
HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset);
|
||||||
HIDDEN(.Lape.note.filesz = .Lape.note.end - .Lape.note);
|
HIDDEN(ape_note_filesz = ape_note_end - ape_note);
|
||||||
HIDDEN(.Lape.note.memsz = .Lape.note.filesz);
|
HIDDEN(ape_note_memsz = ape_note_filesz);
|
||||||
HIDDEN(.Lape.note.align = __SIZEOF_POINTER__);
|
HIDDEN(ape_note_align = __SIZEOF_POINTER__);
|
||||||
|
|
||||||
HIDDEN(.Lape.text.offset = .Lape.rom.offset + LOADADDR(.text) - .Lape.rom.paddr);
|
HIDDEN(ape_text_offset = ape_rom_offset + LOADADDR(.text) - ape_rom_paddr);
|
||||||
HIDDEN(.Lape.text.paddr = LOADADDR(.text));
|
HIDDEN(ape_text_paddr = LOADADDR(.text));
|
||||||
HIDDEN(.Lape.text.vaddr = ADDR(.text));
|
HIDDEN(ape_text_vaddr = ADDR(.text));
|
||||||
HIDDEN(.Lape.text.filesz = SIZEOF(.text));
|
HIDDEN(ape_text_filesz = SIZEOF(.text));
|
||||||
HIDDEN(.Lape.text.memsz = SIZEOF(.text));
|
HIDDEN(ape_text_memsz = SIZEOF(.text));
|
||||||
HIDDEN(.Lape.text.align = 4096);
|
HIDDEN(ape_text_align = PAGESIZE);
|
||||||
HIDDEN(.Lape.text.rva = RVA(.Lape.text.vaddr));
|
HIDDEN(ape_text_rva = RVA(ape_text_vaddr));
|
||||||
|
|
||||||
HIDDEN(.Lape.data.offset = .Lape.ram.offset + LOADADDR(.data) - .Lape.ram.paddr);
|
HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr);
|
||||||
HIDDEN(.Lape.data.paddr = LOADADDR(.data));
|
HIDDEN(ape_data_paddr = LOADADDR(.data));
|
||||||
HIDDEN(.Lape.data.vaddr = ADDR(.data));
|
HIDDEN(ape_data_vaddr = ADDR(.data));
|
||||||
HIDDEN(.Lape.data.filesz = SIZEOF(.data));
|
HIDDEN(ape_data_filesz = SIZEOF(.data));
|
||||||
HIDDEN(.Lape.data.memsz = SIZEOF(.data));
|
HIDDEN(ape_data_memsz = SIZEOF(.data));
|
||||||
HIDDEN(.Lape.data.align = .Lape.data.align);
|
HIDDEN(ape_data_align = PAGESIZE);
|
||||||
HIDDEN(.Lape.data.rva = RVA(.Lape.data.vaddr));
|
HIDDEN(ape_data_rva = RVA(ape_data_vaddr));
|
||||||
|
|
||||||
HIDDEN(.Lape.bss.offset = .Lape.ram.offset + LOADADDR(.bss) - .Lape.ram.paddr);
|
HIDDEN(ape_bss_offset = ape_ram_offset + LOADADDR(.bss) - ape_ram_paddr);
|
||||||
HIDDEN(.Lape.bss.paddr = LOADADDR(.bss));
|
HIDDEN(ape_bss_paddr = LOADADDR(.bss));
|
||||||
HIDDEN(.Lape.bss.vaddr = ADDR(.bss));
|
HIDDEN(ape_bss_vaddr = ADDR(.bss));
|
||||||
HIDDEN(.Lape.bss.filesz = 0);
|
HIDDEN(ape_bss_filesz = 0);
|
||||||
HIDDEN(.Lape.bss.memsz = SIZEOF(.bss));
|
HIDDEN(ape_bss_memsz = SIZEOF(.bss));
|
||||||
HIDDEN(.Lape.bss.align = .Lape.data.align);
|
HIDDEN(ape_bss_align = PAGESIZE);
|
||||||
|
|
||||||
#if SupportsXnu()
|
#if SupportsXnu()
|
||||||
SHSTUB2(.Lape.macho.dd.skip, RVA(ape.macho) / 8);
|
SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
|
||||||
SHSTUB2(.Lape.macho.dd.count, (.Lape.macho.end - ape.macho) / 8);
|
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
PFSTUB4(.Lape.pe.offset, ape.pe - ape.mz);
|
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
|
||||||
HIDDEN(.Lape.pe.optsz = .Lape.pe.sections - (ape.pe + 24));
|
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
|
||||||
HIDDEN(.Lape.pe.shnum = (.Lape.pe.sections_end - .Lape.pe.sections) / 40);
|
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
|
||||||
HIDDEN(.Lidata.idtsize = idata.idtend - idata.idt);
|
HIDDEN(ape_idata_idtsize = ape_idata_idtend - ape_idata_idt);
|
||||||
HIDDEN(.Lidata.iatsize = idata.iatend - idata.iat);
|
HIDDEN(ape_idata_iatsize = ape_idata_iatend - ape_idata_iat);
|
||||||
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage)
|
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage)
|
||||||
? kNtImageSubsystemWindowsGui
|
? kNtImageSubsystemWindowsGui
|
||||||
: kNtImageSubsystemWindowsCui));
|
: kNtImageSubsystemWindowsCui));
|
||||||
|
@ -577,90 +543,89 @@ ZIPCONST(v_zip_commentsize, _edata - __zip_end - kZipCdirHdrMinSize);
|
||||||
X = (X + (Y >> 020) & 0xFF) * PHI; \
|
X = (X + (Y >> 020) & 0xFF) * PHI; \
|
||||||
X = (X + (Y >> 030) & 0xFF) * PHI
|
X = (X + (Y >> 030) & 0xFF) * PHI
|
||||||
#define CHURN(X) \
|
#define CHURN(X) \
|
||||||
XORSHIFT(.Lape.uuid1, X); \
|
XORSHIFT(ape_uuid1, X); \
|
||||||
KMH(.Lape.uuid1, X); \
|
KMH(ape_uuid1, X); \
|
||||||
XORSHIFT(.Lape.uuid2, X); \
|
XORSHIFT(ape_uuid2, X); \
|
||||||
KMH(.Lape.uuid2, X)
|
KMH(ape_uuid2, X)
|
||||||
HIDDEN(.Lape.uuid1 = 88172645463325252);
|
HIDDEN(ape_uuid1 = 88172645463325252);
|
||||||
HIDDEN(.Lape.uuid2 = 88172645463325252);
|
HIDDEN(ape_uuid2 = 88172645463325252);
|
||||||
CHURN(.Lape.bss.align);
|
CHURN(ape_bss_align);
|
||||||
CHURN(.Lape.bss.filesz);
|
CHURN(ape_bss_filesz);
|
||||||
CHURN(.Lape.bss.memsz);
|
CHURN(ape_bss_memsz);
|
||||||
CHURN(.Lape.bss.offset);
|
CHURN(ape_bss_offset);
|
||||||
CHURN(.Lape.bss.paddr);
|
CHURN(ape_bss_paddr);
|
||||||
CHURN(.Lape.data.align);
|
CHURN(ape_data_filesz);
|
||||||
CHURN(.Lape.data.filesz);
|
CHURN(ape_data_memsz);
|
||||||
CHURN(.Lape.data.memsz);
|
CHURN(ape_data_offset);
|
||||||
CHURN(.Lape.data.offset);
|
CHURN(ape_data_paddr);
|
||||||
CHURN(.Lape.data.paddr);
|
CHURN(ape_data_rva);
|
||||||
CHURN(.Lape.data.rva);
|
CHURN(ape_data_vaddr);
|
||||||
CHURN(.Lape.data.vaddr);
|
CHURN(ape_elf_entry);
|
||||||
CHURN(.Lape.elf.entry);
|
CHURN(ape_elf_phnum);
|
||||||
CHURN(.Lape.elf.phnum);
|
CHURN(ape_elf_phoff);
|
||||||
CHURN(.Lape.elf.phoff);
|
CHURN(ape_elf_shnum);
|
||||||
CHURN(.Lape.elf.shnum);
|
CHURN(ape_elf_shoff);
|
||||||
CHURN(.Lape.elf.shoff);
|
CHURN(ape_elf_shstrndx);
|
||||||
CHURN(.Lape.elf.shstrndx);
|
CHURN(ape_macho_end);
|
||||||
CHURN(.Lape.macho.end);
|
CHURN(ape_note);
|
||||||
CHURN(.Lape.note);
|
CHURN(ape_note_align);
|
||||||
CHURN(.Lape.note.align);
|
CHURN(ape_note_end);
|
||||||
CHURN(.Lape.note.end);
|
CHURN(ape_note_filesz);
|
||||||
CHURN(.Lape.note.filesz);
|
CHURN(ape_note_memsz);
|
||||||
CHURN(.Lape.note.memsz);
|
CHURN(ape_note_offset);
|
||||||
CHURN(.Lape.note.offset);
|
CHURN(ape_note_paddr);
|
||||||
CHURN(.Lape.note.paddr);
|
CHURN(ape_note_vaddr);
|
||||||
CHURN(.Lape.note.vaddr);
|
CHURN(ape_ram_align);
|
||||||
CHURN(.Lape.ram.align);
|
CHURN(ape_ram_filesz);
|
||||||
CHURN(.Lape.ram.filesz);
|
CHURN(ape_ram_memsz);
|
||||||
CHURN(.Lape.ram.memsz);
|
CHURN(ape_ram_offset);
|
||||||
CHURN(.Lape.ram.offset);
|
CHURN(ape_ram_paddr);
|
||||||
CHURN(.Lape.ram.paddr);
|
CHURN(ape_ram_rva);
|
||||||
CHURN(.Lape.ram.rva);
|
CHURN(ape_ram_vaddr);
|
||||||
CHURN(.Lape.ram.vaddr);
|
CHURN(ape_rom_align);
|
||||||
CHURN(.Lape.rom.align);
|
CHURN(ape_rom_filesz);
|
||||||
CHURN(.Lape.rom.filesz);
|
CHURN(ape_rom_memsz);
|
||||||
CHURN(.Lape.rom.memsz);
|
CHURN(ape_rom_offset);
|
||||||
CHURN(.Lape.rom.offset);
|
CHURN(ape_rom_paddr);
|
||||||
CHURN(.Lape.rom.paddr);
|
CHURN(ape_rom_rva);
|
||||||
CHURN(.Lape.rom.rva);
|
CHURN(ape_rom_vaddr);
|
||||||
CHURN(.Lape.rom.vaddr);
|
CHURN(ape_text_align);
|
||||||
CHURN(.Lape.text.align);
|
CHURN(ape_text_filesz);
|
||||||
CHURN(.Lape.text.filesz);
|
CHURN(ape_text_memsz);
|
||||||
CHURN(.Lape.text.memsz);
|
CHURN(ape_text_offset);
|
||||||
CHURN(.Lape.text.offset);
|
CHURN(ape_text_paddr);
|
||||||
CHURN(.Lape.text.paddr);
|
CHURN(ape_text_rva);
|
||||||
CHURN(.Lape.text.rva);
|
CHURN(ape_text_vaddr);
|
||||||
CHURN(.Lape.text.vaddr);
|
|
||||||
CHURN(ADDR(.bss));
|
CHURN(ADDR(.bss));
|
||||||
CHURN(_start);
|
CHURN(_start);
|
||||||
CHURN(ape.phdrs);
|
CHURN(ape_phdrs);
|
||||||
#if SupportsMetal()
|
#if SupportsMetal()
|
||||||
CHURN(v_ape_realsectors);
|
CHURN(v_ape_realsectors);
|
||||||
#endif
|
#endif
|
||||||
#if SupportsXnu()
|
#if SupportsXnu()
|
||||||
CHURN(ape.macho);
|
CHURN(ape_macho);
|
||||||
#endif
|
#endif
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
CHURN(ape.mz);
|
CHURN(ape_mz);
|
||||||
CHURN(ape.pe);
|
CHURN(ape_pe);
|
||||||
CHURN(.Lape.pe.offset);
|
CHURN(ape_pe_offset);
|
||||||
CHURN(.Lape.pe.optsz);
|
CHURN(ape_pe_optsz);
|
||||||
CHURN(.Lape.pe.sections);
|
CHURN(ape_pe_sections);
|
||||||
CHURN(.Lape.pe.sections_end);
|
CHURN(ape_pe_sections_end);
|
||||||
CHURN(.Lape.pe.shnum);
|
CHURN(ape_pe_shnum);
|
||||||
CHURN(.Lape.phdrs.end);
|
CHURN(ape_phdrs_end);
|
||||||
CHURN(WinMain);
|
CHURN(WinMain);
|
||||||
#endif /* SupportsWindows() */
|
#endif /* SupportsWindows() */
|
||||||
#endif /* SupportsXnu() */
|
#endif /* SupportsXnu() */
|
||||||
|
|
||||||
ASSERT(DEFINED(ape.mz) ? ape.mz == IMAGE_BASE_VIRTUAL : 1, "linker panic");
|
ASSERT(DEFINED(ape_mz) ? ape_mz == IMAGE_BASE_VIRTUAL : 1, "linker panic");
|
||||||
ASSERT((DEFINED(__init_bss_end) ? __init_bss_end : 0) % __SIZEOF_POINTER__ == 0,
|
ASSERT((DEFINED(__init_bss_end) ? __init_bss_end : 0) % __SIZEOF_POINTER__ == 0,
|
||||||
"__init_bss misalign");
|
"__init_bss misalign");
|
||||||
ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
|
ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
|
||||||
__SIZEOF_POINTER__ == 0),
|
__SIZEOF_POINTER__ == 0),
|
||||||
"__init_rodata misalign");
|
"__init_rodata misalign");
|
||||||
|
|
||||||
ASSERT((!DEFINED(ape.grub) ? 1 : RVA(ape.grub) < 8192),
|
ASSERT((!DEFINED(ape_grub) ? 1 : RVA(ape_grub) < 8192),
|
||||||
"grub stub needs to be in first 8kb of image");
|
"grub stub needs to be in first 8kb of image");
|
||||||
|
|
||||||
ASSERT(DEFINED(_start) || DEFINED(_start16),
|
ASSERT(DEFINED(_start) || DEFINED(_start16),
|
||||||
|
@ -672,7 +637,7 @@ ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
|
||||||
/* Let's not be like Knight Capital. */
|
/* Let's not be like Knight Capital. */
|
||||||
/* NOCROSSREFS_TO(.test .text) */
|
/* NOCROSSREFS_TO(.test .text) */
|
||||||
|
|
||||||
/* ASSERT(ape_sysv_start == .Lape.text.vaddr, */
|
/* ASSERT(ape_sysv_start == ape_text_vaddr, */
|
||||||
/* "ape_sysv_start() must be first in .text"); */
|
/* "ape_sysv_start() must be first in .text"); */
|
||||||
|
|
||||||
#endif /* __LINKER__ */
|
#endif /* __LINKER__ */
|
||||||
|
|
|
@ -24,12 +24,7 @@ APELINK = \
|
||||||
$(COMPILE) \
|
$(COMPILE) \
|
||||||
$(LINK) \
|
$(LINK) \
|
||||||
$(LINKARGS) \
|
$(LINKARGS) \
|
||||||
$(OUTPUT_OPTION) && \
|
$(OUTPUT_OPTION)
|
||||||
$(STRIP) \
|
|
||||||
-X $@ && \
|
|
||||||
$(GZ) \
|
|
||||||
$(ZFLAGS) \
|
|
||||||
-f $@.map
|
|
||||||
|
|
||||||
APE_FILES := $(wildcard ape/*.*)
|
APE_FILES := $(wildcard ape/*.*)
|
||||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||||
|
|
|
@ -22,15 +22,15 @@
|
||||||
#include "ape/relocations.h"
|
#include "ape/relocations.h"
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
/ Links function from external DLL.
|
// Links function from external DLL.
|
||||||
/
|
//
|
||||||
/ This embeds a function pointer in the binary. The NT Executive
|
// This embeds a function pointer in the binary. The NT Executive
|
||||||
/ fills its value before control is handed off to the program.
|
// fills its value before control is handed off to the program.
|
||||||
/
|
//
|
||||||
/ @note only ELF toolchains are powerful enough to use this
|
// @note only ELF toolchains are powerful enough to use this
|
||||||
/ @see libc/nt/master.sh
|
// @see libc/nt/master.sh
|
||||||
/ @see ape/ape.lds
|
// @see ape/ape.lds
|
||||||
/ @see winimp
|
// @see winimp
|
||||||
.macro .imp dll:req fn:req actual:req hint
|
.macro .imp dll:req fn:req actual:req hint
|
||||||
.dll \dll
|
.dll \dll
|
||||||
.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
|
.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
|
||||||
|
@ -63,10 +63,10 @@
|
||||||
.previous
|
.previous
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Defines DLL import.
|
// Defines DLL import.
|
||||||
/ @note this is an implementation detail of .imp
|
// @note this is an implementation detail of .imp
|
||||||
.macro .dll name:req
|
.macro .dll name:req
|
||||||
.section .idata.ro.idt.2.\name,"aG",\name,comdat
|
.section .idata.ro.idt.2.\name,"aG",@progbits,\name,comdat
|
||||||
.equ .Lidata.idt.\name,.
|
.equ .Lidata.idt.\name,.
|
||||||
.long RVA(idata.ilt.\name) # ImportLookupTable
|
.long RVA(idata.ilt.\name) # ImportLookupTable
|
||||||
.long 0 # TimeDateStamp
|
.long 0 # TimeDateStamp
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
.type .Lidata.idt.\name,@object
|
.type .Lidata.idt.\name,@object
|
||||||
.size .Lidata.idt.\name,.-.Lidata.idt.\name
|
.size .Lidata.idt.\name,.-.Lidata.idt.\name
|
||||||
.previous
|
.previous
|
||||||
.section .idata.ro.ilt.\name\().1,"aG",\name,comdat
|
.section .idata.ro.ilt.\name\().1,"aG",@progbits,\name,comdat
|
||||||
.align __SIZEOF_POINTER__
|
.align __SIZEOF_POINTER__
|
||||||
.type idata.ilt.\name,@object
|
.type idata.ilt.\name,@object
|
||||||
idata.ilt.\name:
|
idata.ilt.\name:
|
||||||
|
@ -84,15 +84,15 @@ idata.ilt.\name:
|
||||||
...
|
...
|
||||||
decentralized content
|
decentralized content
|
||||||
...
|
...
|
||||||
*/.section .idata.ro.ilt.\name\().3,"aG",\name,comdat
|
*/.section .idata.ro.ilt.\name\().3,"aG",@progbits,\name,comdat
|
||||||
.quad 0
|
.quad 0
|
||||||
.previous
|
.previous
|
||||||
.section .idata.ro.hnt.\name\().1,"aG",\name,comdat
|
.section .idata.ro.hnt.\name\().1,"aG",@progbits,\name,comdat
|
||||||
.align __SIZEOF_POINTER__
|
.align __SIZEOF_POINTER__
|
||||||
.type idata.hnt.\name,@object
|
.type idata.hnt.\name,@object
|
||||||
.equ idata.hnt.\name,.
|
.equ idata.hnt.\name,.
|
||||||
.previous
|
.previous
|
||||||
.section .piro.data.sort.iat.2.\name\().1,"awG",\name,comdat
|
.section .piro.data.sort.iat.2.\name\().1,"awG",@progbits,\name,comdat
|
||||||
.align __SIZEOF_POINTER__
|
.align __SIZEOF_POINTER__
|
||||||
.type idata.iat.\name,@object
|
.type idata.iat.\name,@object
|
||||||
idata.iat.\name:
|
idata.iat.\name:
|
||||||
|
@ -100,7 +100,7 @@ idata.iat.\name:
|
||||||
...
|
...
|
||||||
decentralized content
|
decentralized content
|
||||||
...
|
...
|
||||||
*/.section .piro.data.sort.iat.2.\name\().3,"awG",\name,comdat
|
*/.section .piro.data.sort.iat.2.\name\().3,"awG",@progbits,\name,comdat
|
||||||
.quad 0
|
.quad 0
|
||||||
.previous
|
.previous
|
||||||
.section .rodata.str1.1,"aSM",@progbits,1
|
.section .rodata.str1.1,"aSM",@progbits,1
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
.code16
|
.code16
|
||||||
|
|
||||||
/ Resets personal computer.
|
// Resets personal computer.
|
||||||
/
|
//
|
||||||
/ @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
|
// @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
|
||||||
/ @mode real
|
// @mode real
|
||||||
/ @noreturn
|
// @noreturn
|
||||||
bootdr: push %bp
|
bootdr: push %bp
|
||||||
mov %sp,%bp
|
mov %sp,%bp
|
||||||
mov %di,%dx
|
mov %di,%dx
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
.hidden e820map
|
.hidden e820map
|
||||||
.type e820map,@object
|
.type e820map,@object
|
||||||
.size e820map,XLM_E820_SIZE
|
.size e820map,XLM_E820_SIZE
|
||||||
e820map = ape.xlm + XLM_E820
|
e820map = ape_xlm + XLM_E820
|
||||||
|
|
||||||
.globl e820map_xlm
|
.globl e820map_xlm
|
||||||
.hidden e820map_xlm
|
.hidden e820map_xlm
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
.hidden g_ptsp
|
.hidden g_ptsp
|
||||||
.type g_ptsp,@object
|
.type g_ptsp,@object
|
||||||
.size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE
|
.size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE
|
||||||
g_ptsp = ape.xlm + XLM_PAGE_TABLE_STACK_POINTER
|
g_ptsp = ape_xlm + XLM_PAGE_TABLE_STACK_POINTER
|
||||||
|
|
||||||
.globl g_ptsp_xlm
|
.globl g_ptsp_xlm
|
||||||
.hidden g_ptsp_xlm
|
.hidden g_ptsp_xlm
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
.hidden kBiosDataArea
|
.hidden kBiosDataArea
|
||||||
.type kBiosDataArea,@object
|
.type kBiosDataArea,@object
|
||||||
.size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE
|
.size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE
|
||||||
kBiosDataArea = ape.xlm + XLM_BIOS_DATA_AREA
|
kBiosDataArea = ape_xlm + XLM_BIOS_DATA_AREA
|
||||||
|
|
||||||
.globl kBiosDataAreaXlm
|
.globl kBiosDataAreaXlm
|
||||||
.hidden kBiosDataAreaXlm
|
.hidden kBiosDataAreaXlm
|
||||||
|
|
80
ape/lib/pc.h
80
ape/lib/pc.h
|
@ -63,49 +63,49 @@
|
||||||
#define FPU_C2 0b0000000000000010000000000
|
#define FPU_C2 0b0000000000000010000000000
|
||||||
#define FPU_C3 0b0000000000100000000000000
|
#define FPU_C3 0b0000000000100000000000000
|
||||||
|
|
||||||
#define CR0_PE (1u << 0) /* protected mode enabled */
|
#define CR0_PE 0x01 /* protected mode enabled */
|
||||||
#define CR0_MP (1u << 1) /* monitor coprocessor */
|
#define CR0_MP 0x02 /* monitor coprocessor */
|
||||||
#define CR0_EM (1u << 2) /* no x87 fpu present if set */
|
#define CR0_EM 0x04 /* no x87 fpu present if set */
|
||||||
#define CR0_TS (1u << 3) /* task switched x87 */
|
#define CR0_TS 0x08 /* task switched x87 */
|
||||||
#define CR0_ET (1u << 4) /* extension type 287 or 387 */
|
#define CR0_ET 0x10 /* extension type 287 or 387 */
|
||||||
#define CR0_NE (1u << 5) /* enable x87 error reporting */
|
#define CR0_NE 0x20 /* enable x87 error reporting */
|
||||||
#define CR0_WP (1u << 16) /* write protect read-only pages @pl0 */
|
#define CR0_WP 0x00010000 /* write protect read-only pages @pl0 */
|
||||||
#define CR0_AM (1u << 18) /* alignment mask */
|
#define CR0_AM 0x00040000 /* alignment mask */
|
||||||
#define CR0_NW (1u << 29) /* global write-through cache disable */
|
#define CR0_NW 0x20000000 /* global write-through cache disable */
|
||||||
#define CR0_CD (1u << 30) /* global cache disable */
|
#define CR0_CD 0x40000000 /* global cache disable */
|
||||||
#define CR0_PG (1u << 31) /* paging enabled */
|
#define CR0_PG 0x80000000 /* paging enabled */
|
||||||
|
|
||||||
#define CR4_VME (1u << 0) /* virtual 8086 mode extension */
|
#define CR4_VME 0x01 /* virtual 8086 mode extension */
|
||||||
#define CR4_PVI (1u << 1) /* protected mode virtual interrupts */
|
#define CR4_PVI 0x02 /* protected mode virtual interrupts */
|
||||||
#define CR4_TSD (1u << 2) /* time stamp disable (rdtsc) */
|
#define CR4_TSD 0x04 /* time stamp disable (rdtsc) */
|
||||||
#define CR4_DE (1u << 3) /* debugging extensions */
|
#define CR4_DE 0x08 /* debugging extensions */
|
||||||
#define CR4_PSE (1u << 4) /* page size extension */
|
#define CR4_PSE 0x10 /* page size extension */
|
||||||
#define CR4_PAE (1u << 5) /* physical address extension */
|
#define CR4_PAE 0x20 /* physical address extension */
|
||||||
#define CR4_MCE (1u << 6) /* machine check exception */
|
#define CR4_MCE 0x40 /* machine check exception */
|
||||||
#define CR4_PGE (1u << 7) /* page global enabled */
|
#define CR4_PGE 0x80 /* page global enabled */
|
||||||
#define CR4_OSFXSR (1u << 9) /* enable SSE and fxsave/fxrestor */
|
#define CR4_OSFXSR 0x0200 /* enable SSE and fxsave/fxrestor */
|
||||||
#define CR4_OSXMMEXCPT (1u << 10) /* enable unmasked SSE exceptions */
|
#define CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
|
||||||
#define CR4_LA57 (1u << 12) /* enable level-5 paging */
|
#define CR4_LA57 0x1000 /* enable level-5 paging */
|
||||||
#define CR4_VMXE (1u << 13) /* enable VMX operations */
|
#define CR4_VMXE 0x2000 /* enable VMX operations */
|
||||||
#define CR4_SMXE (1u << 14) /* enable SMX operations */
|
#define CR4_SMXE 0x4000 /* enable SMX operations */
|
||||||
#define CR4_FSGSBASE (1u << 16) /* enable *FSBASE and *GSBASE instructions */
|
#define CR4_FSGSBASE 0x00010000 /* enable *FSBASE and *GSBASE instructions */
|
||||||
#define CR4_PCIDE (1u << 17) /* enable process-context identifiers */
|
#define CR4_PCIDE 0x00020000 /* enable process-context identifiers */
|
||||||
#define CR4_OSXSAVE (1u << 18) /* enable XSAVE */
|
#define CR4_OSXSAVE 0x00040000 /* enable XSAVE */
|
||||||
|
|
||||||
#define XCR0_X87 (1u << 0)
|
#define XCR0_X87 0x01
|
||||||
#define XCR0_SSE (1u << 1)
|
#define XCR0_SSE 0x02
|
||||||
#define XCR0_AVX (1u << 2)
|
#define XCR0_AVX 0x04
|
||||||
#define XCR0_BNDREG (1u << 3)
|
#define XCR0_BNDREG 0x08
|
||||||
#define XCR0_BNDCSR (1u << 4)
|
#define XCR0_BNDCSR 0x10
|
||||||
#define XCR0_OPMASK (1u << 5)
|
#define XCR0_OPMASK 0x20
|
||||||
#define XCR0_ZMM_HI256 (1u << 6)
|
#define XCR0_ZMM_HI256 0x40
|
||||||
#define XCR0_HI16_ZMM (1u << 7)
|
#define XCR0_HI16_ZMM 0x80
|
||||||
|
|
||||||
#define EFER 0xC0000080 /* extended feature enable register */
|
#define EFER 0xc0000080 /* extended feature enable register */
|
||||||
#define EFER_SCE (1u << 0) /* system call extensions */
|
#define EFER_SCE 0x01 /* system call extensions */
|
||||||
#define EFER_LME (1u << 8) /* long mode enable */
|
#define EFER_LME 0x0100 /* long mode enable */
|
||||||
#define EFER_LMA (1u << 10) /* long mode active */
|
#define EFER_LMA 0x0400 /* long mode active */
|
||||||
#define EFER_NXE (1u << 11) /* no-execute enable */
|
#define EFER_NXE 0x0800 /* no-execute enable */
|
||||||
|
|
||||||
#define GDT_REAL_CODE 8
|
#define GDT_REAL_CODE 8
|
||||||
#define GDT_REAL_DATA 16
|
#define GDT_REAL_DATA 16
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
/*-*- 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. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#ifndef APE_MACROS_H_
|
#ifndef APE_MACROS_H_
|
||||||
#define APE_MACROS_H_
|
#define APE_MACROS_H_
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
@ -8,9 +26,16 @@
|
||||||
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
|
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/ Calls near (i.e. pc+pcrel<64kB) FUNCTION.
|
// Calls function in real mode.
|
||||||
/ @mode long,legacy,real
|
// It's needed because LLVM 8 LLD doesn't support R_X86_64_PC16.
|
||||||
/ @cost 9 bytes overhead
|
.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
|
||||||
.macro rlcall function:req
|
.macro rlcall function:req
|
||||||
.byte 0x50 # push %[er]ax
|
.byte 0x50 # push %[er]ax
|
||||||
.byte 0xb8,0,0 # mov $?,%[e]ax
|
.byte 0xb8,0,0 # mov $?,%[e]ax
|
||||||
|
@ -25,8 +50,8 @@
|
||||||
912:
|
912:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
|
// Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro movesdi address:req
|
.macro movesdi address:req
|
||||||
.byte 0xbf # mov $0x????xxxx,%[e]di
|
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||||
.short \address>>4
|
.short \address>>4
|
||||||
|
@ -39,8 +64,8 @@
|
||||||
297:
|
297:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
|
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
|
||||||
.ifnb \abcd
|
.ifnb \abcd
|
||||||
.if (\constexpr)<128 && (\constexpr)>=0
|
.if (\constexpr)<128 && (\constexpr)>=0
|
||||||
|
@ -52,8 +77,8 @@
|
||||||
movb $(\constexpr)&0xff,\abcd.lo
|
movb $(\constexpr)&0xff,\abcd.lo
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Compares 16-bit CONSTEXPR with Qw-register.
|
// Compares 16-bit CONSTEXPR with Qw-register.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
|
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
|
||||||
cmpb $(\constexpr)>>8&0xff,\abcd.hi
|
cmpb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
jnz 387f
|
jnz 387f
|
||||||
|
@ -61,8 +86,8 @@
|
||||||
387:
|
387:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Adds 16-bit CONSTEXPR to Qw-register.
|
// Adds 16-bit CONSTEXPR to Qw-register.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
|
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
|
||||||
addb $(\constexpr)&0xff,\abcd.lo
|
addb $(\constexpr)&0xff,\abcd.lo
|
||||||
.if (\constexpr) != 0
|
.if (\constexpr) != 0
|
||||||
|
@ -70,8 +95,8 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Subtracts 16-bit CONSTEXPR from Qw-register.
|
// Subtracts 16-bit CONSTEXPR from Qw-register.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
|
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
|
||||||
subb $(\constexpr)&0xff,\abcd.lo
|
subb $(\constexpr)&0xff,\abcd.lo
|
||||||
.if (\constexpr) != 0
|
.if (\constexpr) != 0
|
||||||
|
@ -79,8 +104,8 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Ands Qw-register with 16-bit CONSTEXPR.
|
// Ands Qw-register with 16-bit CONSTEXPR.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro bband constexpr:req abcd.hi:req abcd.lo:req
|
.macro bband constexpr:req abcd.hi:req abcd.lo:req
|
||||||
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
|
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
|
||||||
andb $(\constexpr)&0xff,\abcd.lo
|
andb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
@ -90,8 +115,8 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Ors Qw-register with 16-bit CONSTEXPR.
|
// Ors Qw-register with 16-bit CONSTEXPR.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
|
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
|
||||||
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
|
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
|
||||||
orb $(\constexpr)&0xff,\abcd.lo
|
orb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
@ -101,8 +126,8 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Performs ACTION only if in real mode.
|
// Performs ACTION only if in real mode.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro rlo clobber:req action:vararg
|
.macro rlo clobber:req action:vararg
|
||||||
990: mov $0,\clobber
|
990: mov $0,\clobber
|
||||||
.if .-990b!=3
|
.if .-990b!=3
|
||||||
|
@ -117,10 +142,10 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Initializes real mode stack.
|
// Initializes real mode stack.
|
||||||
/ The most holiest of holy code.
|
// The most holiest of holy code.
|
||||||
/ @mode real
|
// @mode real
|
||||||
/ @see www.pcjs.org/pubs/pc/reference/intel/8086/
|
// @see www.pcjs.org/pubs/pc/reference/intel/8086/
|
||||||
.macro rlstack seg:req addr:req
|
.macro rlstack seg:req addr:req
|
||||||
cli
|
cli
|
||||||
mov \seg,%ss
|
mov \seg,%ss
|
||||||
|
@ -128,7 +153,7 @@
|
||||||
sti
|
sti
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Symbolic Linker-Defined Binary Content.
|
// Symbolic Linker-Defined Binary Content.
|
||||||
.macro .stub name:req kind:req default type=@object
|
.macro .stub name:req kind:req default type=@object
|
||||||
.ifnb \default
|
.ifnb \default
|
||||||
.equ \name,\default
|
.equ \name,\default
|
||||||
|
@ -139,17 +164,17 @@
|
||||||
.hidden \name
|
.hidden \name
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Symbolic Linker-Defined Binary-Encoded-Bourne Content.
|
// Symbolic Linker-Defined Binary-Encoded-Bourne Content.
|
||||||
/ @param units is the number of encoded 32-bit values to insert,
|
// @param units is the number of encoded 32-bit values to insert,
|
||||||
/ e.g. \000 can be encoded as 0x3030305c.
|
// e.g. \000 can be encoded as 0x3030305c.
|
||||||
.macro .shstub name:req units:req
|
.macro .shstub name:req num:req
|
||||||
ss \name,0
|
ss \name,0
|
||||||
.if \units>1
|
.if \num>1
|
||||||
ss \name,1
|
ss \name,1
|
||||||
.if \units>2
|
.if \num>2
|
||||||
ss \name,2
|
ss \name,2
|
||||||
ss \name,3
|
ss \name,3
|
||||||
.if \units>4
|
.if \num>4
|
||||||
ss \name,4
|
ss \name,4
|
||||||
ss \name,5
|
ss \name,5
|
||||||
ss \name,6
|
ss \name,6
|
||||||
|
@ -166,8 +191,8 @@
|
||||||
#elif defined(__LINKER__)
|
#elif defined(__LINKER__)
|
||||||
|
|
||||||
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||||
#define BCXSTUB(SYM, X) \
|
#define BCXSTUB(SYM, X) \
|
||||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||||
|
|
|
@ -15,16 +15,16 @@
|
||||||
# build/archive rcsD library.a foo.o ...
|
# build/archive rcsD library.a foo.o ...
|
||||||
|
|
||||||
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
|
||||||
# if [ -x "o/$MODE/tool/build/ar.com" ]; then
|
if [ -x "o//tool/build/ar.com" ]; then
|
||||||
# set -- "o/$MODE/tool/build/ar.com" "$@"
|
set -- "o//tool/build/ar.com" "$@"
|
||||||
# else
|
else
|
||||||
if [ ! -x o/build/bootstrap/ar.com ]; then
|
if [ ! -x o/build/bootstrap/ar.com ]; then
|
||||||
mkdir -p o/build/bootstrap &&
|
mkdir -p o/build/bootstrap &&
|
||||||
cp -f build/bootstrap/ar.com o/build/bootstrap/ar.com.$$ &&
|
cp -f build/bootstrap/ar.com o/build/bootstrap/ar.com.$$ &&
|
||||||
mv -f o/build/bootstrap/ar.com.$$ o/build/bootstrap/ar.com || exit
|
mv -f o/build/bootstrap/ar.com.$$ o/build/bootstrap/ar.com || exit
|
||||||
|
fi
|
||||||
|
set -- o/build/bootstrap/ar.com "$@"
|
||||||
fi
|
fi
|
||||||
set -- o/build/bootstrap/ar.com "$@"
|
|
||||||
# fi
|
|
||||||
OUT=$3
|
OUT=$3
|
||||||
|
|
||||||
printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2
|
printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -20,8 +20,6 @@ CONFIG_CCFLAGS += \
|
||||||
TARGET_ARCH ?= \
|
TARGET_ARCH ?= \
|
||||||
-msse3
|
-msse3
|
||||||
|
|
||||||
RAGELFLAGS ?= -G2
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Optimized Mode
|
# Optimized Mode
|
||||||
|
@ -48,8 +46,6 @@ CONFIG_CCFLAGS += \
|
||||||
TARGET_ARCH ?= \
|
TARGET_ARCH ?= \
|
||||||
-march=native
|
-march=native
|
||||||
|
|
||||||
RAGELFLAGS ?= -G2
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Release Mode
|
# Release Mode
|
||||||
|
@ -73,8 +69,6 @@ CONFIG_CCFLAGS += \
|
||||||
$(BACKTRACES) \
|
$(BACKTRACES) \
|
||||||
-O2
|
-O2
|
||||||
|
|
||||||
RAGELFLAGS = -G2
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Debug Mode
|
# Debug Mode
|
||||||
|
@ -247,6 +241,23 @@ TARGET_ARCH ?= \
|
||||||
-msse3
|
-msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# LLVM Mode
|
||||||
|
ifeq ($(MODE), llvm)
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
|
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
|
||||||
|
AS = clang
|
||||||
|
CC = clang
|
||||||
|
CXX = clang++
|
||||||
|
CXXFILT = llvm-c++filt
|
||||||
|
LD = ld.lld
|
||||||
|
NM = llvm-nm
|
||||||
|
GCC = clang
|
||||||
|
STRIP = llvm-strip
|
||||||
|
OBJCOPY = llvm-objcopy
|
||||||
|
OBJDUMP = llvm-objdump
|
||||||
|
ADDR2LINE = llvm-addr2line
|
||||||
|
endif
|
||||||
|
|
||||||
# ANSI Mode
|
# ANSI Mode
|
||||||
#
|
#
|
||||||
# These flags cause GCC to predefine __STRICT_ANSI__. Please be warned
|
# These flags cause GCC to predefine __STRICT_ANSI__. Please be warned
|
||||||
|
|
|
@ -197,17 +197,15 @@ DEFAULT_LDFLAGS = \
|
||||||
-static \
|
-static \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-m elf_x86_64 \
|
-m elf_x86_64 \
|
||||||
--gc-sections \
|
|
||||||
--build-id=none \
|
--build-id=none \
|
||||||
--cref -Map=$@.map \
|
|
||||||
--no-dynamic-linker \
|
--no-dynamic-linker \
|
||||||
-z max-page-size=0x1000 \
|
-z max-page-size=0x1000
|
||||||
-Ttext-segment=$(IMAGE_BASE_VIRTUAL)
|
|
||||||
|
|
||||||
ZIPOBJ_FLAGS = \
|
ZIPOBJ_FLAGS = \
|
||||||
-b$(IMAGE_BASE_VIRTUAL)
|
-b$(IMAGE_BASE_VIRTUAL)
|
||||||
|
|
||||||
ASONLYFLAGS = \
|
ASONLYFLAGS = \
|
||||||
|
-c \
|
||||||
-g \
|
-g \
|
||||||
--debug-prefix-map="$(PWD)"=
|
--debug-prefix-map="$(PWD)"=
|
||||||
|
|
||||||
|
@ -313,7 +311,7 @@ OBJECTIFY.c = $(CC) $(OBJECTIFY.c.flags) -c
|
||||||
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
|
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
|
||||||
PREPROCESS = $(CC) $(PREPROCESS.flags)
|
PREPROCESS = $(CC) $(PREPROCESS.flags)
|
||||||
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
|
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
|
||||||
LINK = build/link $(LD) $(LINK.flags)
|
LINK = $(LD) $(LINK.flags)
|
||||||
ELF = o/libc/elf/elf.lds
|
ELF = o/libc/elf/elf.lds
|
||||||
ELFLINK = ACTION=LINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
|
ELFLINK = ACTION=LINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
|
||||||
ARCHIVE = $(AR) $(ARFLAGS)
|
ARCHIVE = $(AR) $(ARFLAGS)
|
||||||
|
|
|
@ -37,7 +37,7 @@ o/%.greg.o: %.greg.c; @ACTION=OBJECTIFY.greg $(COMPILE) $(OBJECTIFY.greg.c) $(OU
|
||||||
o/%.zip.o: o/%; @build/zipobj $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
o/%.zip.o: o/%; @build/zipobj $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
o/$(MODE)/%.a:; @$(ARCHIVE) $@ $^
|
o/$(MODE)/%.a:; @$(ARCHIVE) $@ $^
|
||||||
o/$(MODE)/%: o/$(MODE)/%.dbg; @ACTION=OBJCOPY TARGET=$@ $(COMPILE) $(OBJCOPY) -SO binary $< $@
|
o/$(MODE)/%: o/$(MODE)/%.dbg; @ACTION=OBJCOPY TARGET=$@ $(COMPILE) $(OBJCOPY) -S -O binary $< $@
|
||||||
o/$(MODE)/%.o: %.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
o/$(MODE)/%.o: %.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||||
o/$(MODE)/%.o: o/$(MODE)/%.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
o/$(MODE)/%.o: o/$(MODE)/%.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||||
o/$(MODE)/%.s: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $<
|
o/$(MODE)/%.s: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||||
|
|
|
@ -6,5 +6,6 @@ DD=${DD:-$(command -v dd)} || exit
|
||||||
$DD if="$1" of="$1.bak" bs=4096 count=1 conv=notrunc 2>/dev/null
|
$DD if="$1" of="$1.bak" bs=4096 count=1 conv=notrunc 2>/dev/null
|
||||||
"$@"
|
"$@"
|
||||||
rc=$?
|
rc=$?
|
||||||
|
echo "$1"
|
||||||
$DD if="$1.bak" of="$1" bs=4096 count=1 conv=notrunc 2>/dev/null
|
$DD if="$1.bak" of="$1" bs=4096 count=1 conv=notrunc 2>/dev/null
|
||||||
exit $rc
|
exit $rc
|
||||||
|
|
|
@ -20,18 +20,18 @@
|
||||||
|
|
||||||
#define BIAS 0x84
|
#define BIAS 0x84
|
||||||
|
|
||||||
/ Encodes audio sample with µ-Law.
|
// Encodes audio sample with µ-Law.
|
||||||
/
|
//
|
||||||
/ This is both the highest quality and most widely supported
|
// This is both the highest quality and most widely supported
|
||||||
/ telephony codec, whose use was phased out in the 2000's in
|
// telephony codec, whose use was phased out in the 2000's in
|
||||||
/ favor of cost-saving GSM audio compression that was so bad
|
// favor of cost-saving GSM audio compression that was so bad
|
||||||
/ consumers were willing to pay more cash, for the privilege
|
// consumers were willing to pay more cash, for the privilege
|
||||||
/ of saving telcos even more money w/ text messaging. Mu Law
|
// of saving telcos even more money w/ text messaging. Mu Law
|
||||||
/ reduces PCM data to half its original size, by diminishing
|
// reduces PCM data to half its original size, by diminishing
|
||||||
/ audio bands not vocalized by human voice.
|
// audio bands not vocalized by human voice.
|
||||||
/
|
//
|
||||||
/ @param %edi is pcm sample
|
// @param %edi is pcm sample
|
||||||
/ @return %eax is uint8_t encoded sample
|
// @return %eax is uint8_t encoded sample
|
||||||
mulaw: .leafprologue
|
mulaw: .leafprologue
|
||||||
.profilable
|
.profilable
|
||||||
mov $BIAS,%eax
|
mov $BIAS,%eax
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.align 16
|
.align 16
|
||||||
|
|
||||||
/ Mixes audio.
|
// Mixes audio.
|
||||||
/
|
//
|
||||||
/ @param rdi is # aligned int16[16] sample chunks to process
|
// @param rdi is # aligned int16[16] sample chunks to process
|
||||||
/ @param rsi points to aligned pcm s16le input/output memory
|
// @param rsi points to aligned pcm s16le input/output memory
|
||||||
/ @param rdx points to aligned pcm s16le [0..1] input memory
|
// @param rdx points to aligned pcm s16le [0..1] input memory
|
||||||
sad16x8n:
|
sad16x8n:
|
||||||
.leafprologue
|
.leafprologue
|
||||||
.profilable
|
.profilable
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ TODO(jart): write me
|
// TODO(jart): write me
|
||||||
|
|
||||||
movdqa a,%xmm0
|
movdqa a,%xmm0
|
||||||
mpsadbw $0,inv,%xmm0
|
mpsadbw $0,inv,%xmm0
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Returns index of minimum uint16 in array.
|
// Returns index of minimum uint16 in array.
|
||||||
/
|
//
|
||||||
/ @param rdi points to nonempty array
|
// @param rdi points to nonempty array
|
||||||
/ @param rsi is item count divisible by 16
|
// @param rsi is item count divisible by 16
|
||||||
/ @note needs avx2 (haswell+)
|
// @note needs avx2 (haswell+)
|
||||||
windex_avx2:
|
windex_avx2:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Returns index of minimum positive int16 in array.
|
// Returns index of minimum positive int16 in array.
|
||||||
/
|
//
|
||||||
/ @param rdi points to nonempty array
|
// @param rdi points to nonempty array
|
||||||
/ @param esi is 16-byte aligned 8+ / 8 multiple array item count
|
// @param esi is 16-byte aligned 8+ / 8 multiple array item count
|
||||||
/ @note needs sse4 (nehalem+)
|
// @note needs sse4 (nehalem+)
|
||||||
windex_sse4:
|
windex_sse4:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Dispatches to fastest windex() implementation.
|
// Dispatches to fastest windex() implementation.
|
||||||
.initbss 300,_init_windex
|
.initbss 300,_init_windex
|
||||||
windex: .quad 0
|
windex: .quad 0
|
||||||
.endobj windex,globl
|
.endobj windex,globl
|
||||||
|
|
|
@ -48,6 +48,6 @@ int main(int argc, char *argv[]) {
|
||||||
for (int i = 0; i < min(64, argc); ++i) g_log.x()[i] += argc;
|
for (int i = 0; i < min(64, argc); ++i) g_log.x()[i] += argc;
|
||||||
printf("%p %d %d %d\n", (void *)(intptr_t)g_log.x(), g_log.x()[0],
|
printf("%p %d %d %d\n", (void *)(intptr_t)g_log.x(), g_log.x()[0],
|
||||||
g_log.x()[0], g_log.x()[0]);
|
g_log.x()[0], g_log.x()[0]);
|
||||||
delete x;
|
delete[] x;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Example assembly function.
|
// Example assembly function.
|
||||||
/
|
//
|
||||||
/ @note param agnostic
|
// @note param agnostic
|
||||||
/ @note we love stack frames
|
// @note we love stack frames
|
||||||
/ easiest way to do backtraces
|
// easiest way to do backtraces
|
||||||
/ somehow they usually make code faster
|
// somehow they usually make code faster
|
||||||
/ it's convention for keeping stack 16-byte aligned
|
// it's convention for keeping stack 16-byte aligned
|
||||||
/ cpus still devote much to pushing & popping b/c i386
|
// cpus still devote much to pushing & popping b/c i386
|
||||||
MyAsm: push %rbp
|
MyAsm: push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
call MyPrint2
|
call MyPrint2
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
|
||||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/macros.h"
|
|
||||||
.privileged
|
|
||||||
|
|
||||||
/ Tiny Raw Linux Binary Tutorial
|
|
||||||
/
|
|
||||||
/ i.e. how to not use cosmopolitan runtimes at all
|
|
||||||
/ cosmopolitan basically abstracts this
|
|
||||||
/ except for all major platforms
|
|
||||||
/
|
|
||||||
/ make o//examples/raw-linux-hello.elf
|
|
||||||
/ o/examples/raw-linux-hello.elf # about 6kb
|
|
||||||
/
|
|
||||||
/ Next try C but with fancy build tuning
|
|
||||||
/
|
|
||||||
/ make -j8 -O \
|
|
||||||
/ MODE=tiny \
|
|
||||||
/ LDFLAGS+=-s \
|
|
||||||
/ CPPFLAGS+=-DIM_FEELING_NAUGHTY \
|
|
||||||
/ CPPFLAGS+=-DSUPPORT_VECTOR=0b00000001 \
|
|
||||||
/ o/tiny/examples/hello2.elf
|
|
||||||
/ o/tiny/examples/hello2.elf # about 8kb
|
|
||||||
/
|
|
||||||
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
|
|
||||||
/ @see also glibc static binaries which start at 800kb!!!
|
|
||||||
/ @see also go where interfaces sadly disempower ld prune
|
|
||||||
/ @see also the stl where bad linkage is due to tech debt
|
|
||||||
/ @note libc/elf/elf.lds can be tinier with page align off
|
|
||||||
/ @note gas is more powerful than nasm due to rms notation
|
|
||||||
/ @noreturn
|
|
||||||
_start: mov $12,%rdx # arg no. 3 is length
|
|
||||||
getstr "hello world\n",%rsi,%esi # arg no. 2 is memory
|
|
||||||
mov $1,%edi # arg no. 1 is stdout
|
|
||||||
mov $1,%eax # write()
|
|
||||||
syscall # libc/sysv/syscalls.sh
|
|
||||||
mov $0,%edi # arg no. 1 is success status
|
|
||||||
mov $0xE7,%eax # exit_group()
|
|
||||||
syscall # context switch
|
|
||||||
0: rep nop # basic blockading
|
|
||||||
jmp 0b
|
|
||||||
.endfn _start,globl
|
|
||||||
.source __FILE__
|
|
|
@ -4,27 +4,8 @@
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
#if 0
|
|
||||||
/**
|
/* TOOD(jart): DELETE */
|
||||||
* @fileoverview Cosmopolitan Array List.
|
|
||||||
*
|
|
||||||
* This is a generically-typed ArrayList<T> template which follows a
|
|
||||||
* duck-typing philosophy like Python, exporting an interface paradigm
|
|
||||||
* similar to Go, that's implicitly defined by way of macros like Lisp.
|
|
||||||
*
|
|
||||||
* struct MyArrayList {
|
|
||||||
* size_t i; // current item count
|
|
||||||
* size_t n; // current item capacity
|
|
||||||
* T *p; // pointer to array (initially NULL)
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* Any struct with those fields can be used. It's also very important
|
|
||||||
* that other data structures, which reference items in an arraylist, do
|
|
||||||
* so using indices rather than pointers, since realloc() can relocate.
|
|
||||||
*
|
|
||||||
* @see libc/mem/grow.c
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define append(ARRAYLIST, ITEM) concat((ARRAYLIST), (ITEM), 1)
|
#define append(ARRAYLIST, ITEM) concat((ARRAYLIST), (ITEM), 1)
|
||||||
|
|
||||||
|
@ -38,7 +19,7 @@
|
||||||
size_t Idx = List->i; \
|
size_t Idx = List->i; \
|
||||||
if (Idx + Count < List->n || __grow(&List->p, &List->n, SizE, Count)) { \
|
if (Idx + Count < List->n || __grow(&List->p, &List->n, SizE, Count)) { \
|
||||||
memcpy(&List->p[Idx], Item, SizE *Count); \
|
memcpy(&List->p[Idx], Item, SizE *Count); \
|
||||||
atomic_store(&List->i, Idx + Count); \
|
List->i = Idx + Count; \
|
||||||
} else { \
|
} else { \
|
||||||
Idx = -1UL; \
|
Idx = -1UL; \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -234,12 +234,10 @@ intptr_t atomic_store(void *, intptr_t, size_t);
|
||||||
* @return LOCALVAR[0]
|
* @return LOCALVAR[0]
|
||||||
* @see xchg()
|
* @see xchg()
|
||||||
*/
|
*/
|
||||||
#define lockxchg(MEMORY, LOCALVAR) \
|
#define lockxchg(MEMORY, LOCALVAR) \
|
||||||
({ \
|
({ \
|
||||||
_Static_assert( \
|
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
|
||||||
__builtin_types_compatible_p(typeof(*(MEMORY)), typeof(*(LOCALVAR)))); \
|
*(LOCALVAR); \
|
||||||
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
|
|
||||||
*(LOCALVAR); \
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
|
#ifndef COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
|
||||||
#define COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
|
#define COSMOPOLITAN_LIBC_CALLS_SYSCALLS_H_
|
||||||
|
#include "libc/calls/struct/dirent.h"
|
||||||
#include "libc/calls/struct/iovec.h"
|
#include "libc/calls/struct/iovec.h"
|
||||||
#include "libc/calls/struct/rlimit.h"
|
#include "libc/calls/struct/rlimit.h"
|
||||||
#include "libc/calls/struct/rusage.h"
|
#include "libc/calls/struct/rusage.h"
|
||||||
|
@ -62,7 +63,6 @@ COSMOPOLITAN_C_START_
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
typedef int sig_atomic_t;
|
typedef int sig_atomic_t;
|
||||||
typedef struct dirstream DIR;
|
|
||||||
|
|
||||||
extern const struct sigset kSigsetFull;
|
extern const struct sigset kSigsetFull;
|
||||||
extern const struct sigset kSigsetEmpty;
|
extern const struct sigset kSigsetEmpty;
|
||||||
|
@ -102,7 +102,6 @@ int execvp(const char *, char *const[]) paramsnonnull();
|
||||||
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
|
int execvpe(const char *, char *const[], char *const[]) paramsnonnull();
|
||||||
int faccessat(int, const char *, int, uint32_t);
|
int faccessat(int, const char *, int, uint32_t);
|
||||||
int fadvise(int, uint64_t, uint64_t, int);
|
int fadvise(int, uint64_t, uint64_t, int);
|
||||||
int fallocate(int, int32_t, int64_t, int64_t);
|
|
||||||
int fchmod(int, uint32_t) nothrow;
|
int fchmod(int, uint32_t) nothrow;
|
||||||
int fchmodat(int, const char *, uint32_t, uint32_t);
|
int fchmodat(int, const char *, uint32_t, uint32_t);
|
||||||
int fchown(int, uint32_t, uint32_t);
|
int fchown(int, uint32_t, uint32_t);
|
||||||
|
@ -147,7 +146,6 @@ int personality(uint64_t);
|
||||||
int pipe(int[hasatleast 2]);
|
int pipe(int[hasatleast 2]);
|
||||||
int pipe2(int[hasatleast 2], int);
|
int pipe2(int[hasatleast 2], int);
|
||||||
int posix_fadvise(int, uint64_t, uint64_t, int);
|
int posix_fadvise(int, uint64_t, uint64_t, int);
|
||||||
int posix_fallocate(int, int64_t, int64_t);
|
|
||||||
int posix_madvise(void *, uint64_t, int);
|
int posix_madvise(void *, uint64_t, int);
|
||||||
int raise(int);
|
int raise(int);
|
||||||
int readlink(const char *, char *, size_t);
|
int readlink(const char *, char *, size_t);
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/calls/internal.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/nt/enum/fsctl.h"
|
|
||||||
#include "libc/nt/files.h"
|
|
||||||
#include "libc/nt/struct/filezerodatainformation.h"
|
|
||||||
#include "libc/sysv/consts/falloc.h"
|
|
||||||
#include "libc/sysv/errfuns.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manipulates underlying physical medium of file.
|
|
||||||
*
|
|
||||||
* This system call generalizes to many powerful use cases on Linux,
|
|
||||||
* such as creating gigantic sparse files that take up little space.
|
|
||||||
* This API can polyfill a certain subset of parameters safely, e.g.
|
|
||||||
* ones identical to ftruncate(), but errs on the side of caution.
|
|
||||||
*
|
|
||||||
* @param fd must be open for writing
|
|
||||||
* @param mode can be 0, FALLOC_xxx
|
|
||||||
* @param length is how much physical space to reserve / commit
|
|
||||||
* @return 0 on success, or -1 w/ errno
|
|
||||||
* @note limited availability on rhel5 and openbsd
|
|
||||||
* @see ftruncate()
|
|
||||||
*/
|
|
||||||
int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
|
|
||||||
int rc;
|
|
||||||
uint32_t br;
|
|
||||||
if (mode == -1 /* our sysvconsts definition */) return eopnotsupp();
|
|
||||||
if (!mode && !length) return ftruncate(fd, offset);
|
|
||||||
if (IsLinux()) {
|
|
||||||
rc = sys_fallocate(fd, mode, offset, length);
|
|
||||||
if (rc == 0x011d) rc = enosys(); /*RHEL5:CVE-2010-3301*/
|
|
||||||
return rc;
|
|
||||||
} else if (!IsWindows()) {
|
|
||||||
return sys_posix_fallocate(fd, offset, length);
|
|
||||||
} else {
|
|
||||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
|
||||||
if (mode == FALLOC_FL_ZERO_RANGE) {
|
|
||||||
if (DeviceIoControl(
|
|
||||||
g_fds.p[fd].handle, kNtFsctlSetZeroData,
|
|
||||||
&(struct NtFileZeroDataInformation){offset, offset + length},
|
|
||||||
sizeof(struct NtFileZeroDataInformation), NULL, 0, &br, NULL)) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return __winerr();
|
|
||||||
}
|
|
||||||
} else if (!mode && !offset) {
|
|
||||||
/*
|
|
||||||
* this should commit physical space
|
|
||||||
* but not guaranteed zero'd like linux
|
|
||||||
*/
|
|
||||||
return sys_ftruncate_nt(fd, length);
|
|
||||||
} else {
|
|
||||||
return enosys();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,7 +29,6 @@
|
||||||
* since the prior extends logically and the latter physically
|
* since the prior extends logically and the latter physically
|
||||||
* @return 0 on success, or -1 w/ errno
|
* @return 0 on success, or -1 w/ errno
|
||||||
* @asyncsignalsafe
|
* @asyncsignalsafe
|
||||||
* @see fallocate()
|
|
||||||
*/
|
*/
|
||||||
int ftruncate(int fd, int64_t length) {
|
int ftruncate(int fd, int64_t length) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Obtains WIN32 magic path, e.g. GetTempPathA.
|
// Obtains WIN32 magic path, e.g. GetTempPathA.
|
||||||
/
|
//
|
||||||
/ @param rax is address of ANSI path provider function
|
// @param rax is address of ANSI path provider function
|
||||||
/ @param rdi is output buffer
|
// @param rdi is output buffer
|
||||||
/ @param rdx is output buffer size in bytes that's >0
|
// @param rdx is output buffer size in bytes that's >0
|
||||||
/ @return eax is string length w/ NUL that's ≤ edx
|
// @return eax is string length w/ NUL that's ≤ edx
|
||||||
/ @return rdi is rdi+edx
|
// @return rdi is rdi+edx
|
||||||
.text.startup
|
.text.startup
|
||||||
__getntsyspath:
|
__getntsyspath:
|
||||||
push %rbp
|
push %rbp
|
||||||
|
@ -40,14 +40,14 @@ __getntsyspath:
|
||||||
cmovbe %edx,%eax
|
cmovbe %edx,%eax
|
||||||
cmp $1,%eax # leave empty strings empty
|
cmp $1,%eax # leave empty strings empty
|
||||||
jbe 1f
|
jbe 1f
|
||||||
cmpb $'\\,-1(%rdi,%rax) # guarantee trailing slash
|
cmpb $'\\',-1(%rdi,%rax) # guarantee trailing slash
|
||||||
je 1f
|
je 1f
|
||||||
movw $'\\,(%rdi,%rax)
|
movw $'\\',(%rdi,%rax)
|
||||||
inc %eax
|
inc %eax
|
||||||
1: inc %rdi # change backslash to slash
|
1: inc %rdi # change backslash to slash
|
||||||
cmpb $'\\,-1(%rdi)
|
cmpb $'\\',-1(%rdi)
|
||||||
jne 2f
|
jne 2f
|
||||||
movb $'/,-1(%rdi)
|
movb $'/',-1(%rdi)
|
||||||
2: .loop 1b
|
2: .loop 1b
|
||||||
leave
|
leave
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
textwindows int sys_getsetpriority_nt(int which, unsigned who, int value,
|
textwindows int sys_getsetpriority_nt(int which, unsigned who, int value,
|
||||||
int (*impl)(int)) {
|
int (*impl)(int)) {
|
||||||
if (which != PRIO_PROCESS && which != PRIO_PGRP) return einval();
|
if (which != PRIO_PROCESS && which != PRIO_PGRP) return einval();
|
||||||
if (who && abs(who) != getpid() && abs(who) != gettid()) return eopnotsupp();
|
if (who && who != getpid() && who != gettid()) return eopnotsupp();
|
||||||
return impl(value);
|
return impl(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Calls GetTempPathA() w/ different API.
|
// Calls GetTempPathA() w/ different API.
|
||||||
/
|
//
|
||||||
/ @see GetSystemDirectoryA(), GetWindowsDirectoryA()
|
// @see GetSystemDirectoryA(), GetWindowsDirectoryA()
|
||||||
GetTempPathA_flunk:
|
GetTempPathA_flunk:
|
||||||
xchg %rcx,%rdx
|
xchg %rcx,%rdx
|
||||||
jmp *__imp_GetTempPathA(%rip)
|
jmp *__imp_GetTempPathA(%rip)
|
||||||
|
|
|
@ -120,7 +120,6 @@ i32 sys_dup3(i32, i32, i32) hidden;
|
||||||
i32 sys_execve(const char *, char *const[], char *const[]) hidden;
|
i32 sys_execve(const char *, char *const[], char *const[]) hidden;
|
||||||
i32 sys_faccessat(i32, const char *, i32, u32) hidden;
|
i32 sys_faccessat(i32, const char *, i32, u32) hidden;
|
||||||
i32 sys_fadvise(i32, i64, i64, i32) hidden;
|
i32 sys_fadvise(i32, i64, i64, i32) hidden;
|
||||||
i32 sys_fallocate(i64, i32, i64, i64) hidden;
|
|
||||||
i32 sys_fchdir(i32) hidden;
|
i32 sys_fchdir(i32) hidden;
|
||||||
i32 sys_fchmod(i32, u32) hidden;
|
i32 sys_fchmod(i32, u32) hidden;
|
||||||
i32 sys_fchmodat(i32, const char *, u32, u32) hidden;
|
i32 sys_fchmodat(i32, const char *, u32, u32) hidden;
|
||||||
|
@ -158,7 +157,6 @@ i32 sys_openat(i32, const char *, i32, ...) hidden;
|
||||||
i32 sys_pause(void) hidden;
|
i32 sys_pause(void) hidden;
|
||||||
i32 sys_pipe(i32[hasatleast 2]) hidden;
|
i32 sys_pipe(i32[hasatleast 2]) hidden;
|
||||||
i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
|
i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
|
||||||
i32 sys_posix_fallocate(i64, i64, i64) hidden;
|
|
||||||
i32 sys_posix_openpt(i32) hidden;
|
i32 sys_posix_openpt(i32) hidden;
|
||||||
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
||||||
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
|
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
|
||||||
|
@ -277,7 +275,7 @@ ssize_t sys_write_nt(struct Fd *, const struct iovec *, size_t, ssize_t) hidden;
|
||||||
int64_t ntreturn(uint32_t);
|
int64_t ntreturn(uint32_t);
|
||||||
void WinMainForked(void) hidden;
|
void WinMainForked(void) hidden;
|
||||||
void *GetProcAddressModule(const char *, const char *) hidden;
|
void *GetProcAddressModule(const char *, const char *) hidden;
|
||||||
int sys_getsetpriority_nt(int, unsigned, int, int (*)(int));
|
int sys_getsetpriority_nt(int, int, int, int (*)(int));
|
||||||
void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
|
void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
|
||||||
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
|
||||||
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
|
|
||||||
#define BYTES 64
|
#define BYTES 64
|
||||||
|
|
||||||
/ RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
|
// RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
|
||||||
/
|
//
|
||||||
/ @note guarantees trailing slash if non-empty
|
// @note guarantees trailing slash if non-empty
|
||||||
.initbss 300,_init_kNtSystemDirectory
|
.initbss 300,_init_kNtSystemDirectory
|
||||||
kNtSystemDirectory:
|
kNtSystemDirectory:
|
||||||
.zero BYTES
|
.zero BYTES
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
|
|
||||||
#define BYTES 64
|
#define BYTES 64
|
||||||
|
|
||||||
/ RII constant holding 'C:/WINDOWS' directory.
|
// RII constant holding 'C:/WINDOWS' directory.
|
||||||
/
|
//
|
||||||
/ @note guarantees trailing slash if non-empty
|
// @note guarantees trailing slash if non-empty
|
||||||
.initbss 300,_init_kNtWindowsDirectory
|
.initbss 300,_init_kNtWindowsDirectory
|
||||||
kNtWindowsDirectory:
|
kNtWindowsDirectory:
|
||||||
.zero BYTES
|
.zero BYTES
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
|
|
||||||
#define kTmpPathMax 80
|
#define kTmpPathMax 80
|
||||||
|
|
||||||
/ RII constant holding /tmp/ directory.
|
// RII constant holding /tmp/ directory.
|
||||||
/
|
//
|
||||||
/ @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
|
// @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
|
||||||
/ @note guarantees trailing slash if non-empty
|
// @note guarantees trailing slash if non-empty
|
||||||
.initbss 300,_init_kTmpPath
|
.initbss 300,_init_kTmpPath
|
||||||
kTmpPath:
|
kTmpPath:
|
||||||
.zero kTmpPathMax
|
.zero kTmpPathMax
|
||||||
|
@ -33,8 +33,8 @@ kTmpPath:
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 300,_init_kTmpPath
|
.init.start 300,_init_kTmpPath
|
||||||
movl $'/|'t<<010|'m<<020|'p<<030,(%rdi)
|
movl $'/'|'t'<<010|'m'<<020|'p'<<030,(%rdi)
|
||||||
movw $'/,4(%rdi)
|
movw $'/',4(%rdi)
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
pushpop kTmpPathMax,%rdx
|
pushpop kTmpPathMax,%rdx
|
||||||
ezlea GetTempPathA_flunk,ax
|
ezlea GetTempPathA_flunk,ax
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Returns timestamp without needing system calls.
|
// Returns timestamp without needing system calls.
|
||||||
/
|
//
|
||||||
/ @return seconds since unix epoch in %st0
|
// @return seconds since unix epoch in %st0
|
||||||
/ @note uses microsecond scale fallback on k8 or vm
|
// @note uses microsecond scale fallback on k8 or vm
|
||||||
.initbss 202,_init_nowl
|
.initbss 202,_init_nowl
|
||||||
nowl: .quad 0
|
nowl: .quad 0
|
||||||
.endobj nowl,globl
|
.endobj nowl,globl
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
||||||
│ │
|
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
|
||||||
│ │
|
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/sysv/errfuns.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manipulates underlying physical medium of file, the POSIX way.
|
|
||||||
*
|
|
||||||
* @param fd must be open for writing
|
|
||||||
* @param length is how much physical space to reserve
|
|
||||||
* @return 0 on success, or -1 w/ errno
|
|
||||||
* @see fallocate(), ftruncate()
|
|
||||||
*/
|
|
||||||
int posix_fallocate(int fd, int64_t offset, int64_t length) {
|
|
||||||
return fallocate(fd, 0, offset, length);
|
|
||||||
}
|
|
|
@ -19,18 +19,19 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
errno_t ptsname_r(int fd, char *buf, size_t size) {
|
errno_t ptsname_r(int fd, char *buf, size_t size) {
|
||||||
int pty;
|
int pty;
|
||||||
|
char tb[32];
|
||||||
if (size) {
|
if (size) {
|
||||||
if (!buf) return einval();
|
if (!buf) return einval();
|
||||||
if (ioctl(fd, TIOCGPTN, &pty) == -1) return errno;
|
if (ioctl(fd, TIOCGPTN, &pty) == -1) return errno;
|
||||||
if (snprintf(buf, size, "/dev/pts/%d", pty) >= size) {
|
int64toarray_radix10(pty, stpcpy(tb, "/dev/pts/"));
|
||||||
return (errno = ERANGE);
|
if (strlen(tb) + 1 >= size) return (errno = ERANGE);
|
||||||
}
|
stpcpy(buf, tb);
|
||||||
/* TODO(jart): OpenBSD OMG */
|
/* TODO(jart): OpenBSD OMG */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Sets effective group ID.
|
// Sets effective group ID.
|
||||||
/
|
//
|
||||||
/ @param %edi is group id
|
// @param %edi is group id
|
||||||
/ @see setgid(), getauxval(AT_SECURE)
|
// @see setgid(), getauxval(AT_SECURE)
|
||||||
setegid:push %rbp
|
setegid:push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
.profilable
|
.profilable
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Sets effective user ID.
|
// Sets effective user ID.
|
||||||
/
|
//
|
||||||
/ @param %edi is user id
|
// @param %edi is user id
|
||||||
/ @see setuid(), getauxval(AT_SECURE)
|
// @see setuid(), getauxval(AT_SECURE)
|
||||||
seteuid:push %rbp
|
seteuid:push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
.profilable
|
.profilable
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/assert.h"
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
|
@ -134,15 +135,15 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
|
||||||
* @vforksafe
|
* @vforksafe
|
||||||
*/
|
*/
|
||||||
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
||||||
_Static_assert(sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
|
||||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
|
||||||
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
|
||||||
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
|
||||||
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
|
||||||
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
|
|
||||||
int64_t arg4, arg5;
|
int64_t arg4, arg5;
|
||||||
int rc, rva, oldrva;
|
int rc, rva, oldrva;
|
||||||
struct sigaction *ap, copy;
|
struct sigaction *ap, copy;
|
||||||
|
assert(sizeof(struct sigaction) > sizeof(struct sigaction_linux) &&
|
||||||
|
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_in) &&
|
||||||
|
sizeof(struct sigaction) > sizeof(struct sigaction_xnu_out) &&
|
||||||
|
sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) &&
|
||||||
|
sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) &&
|
||||||
|
sizeof(struct sigaction) > sizeof(struct sigaction_netbsd));
|
||||||
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
|
if (IsMetal()) return enosys(); /* TODO: Signals on Metal */
|
||||||
if (!(0 < sig && sig < NSIG)) return einval();
|
if (!(0 < sig && sig < NSIG)) return einval();
|
||||||
if (sig == SIGKILL || sig == SIGSTOP) return einval();
|
if (sig == SIGKILL || sig == SIGSTOP) return einval();
|
||||||
|
|
|
@ -20,16 +20,16 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ BSD signal handler.
|
// BSD signal handler.
|
||||||
/
|
//
|
||||||
/ This is needed because (1) a signal is allowed to trigger at
|
// This is needed because (1) a signal is allowed to trigger at
|
||||||
/ just about any time, and leaf functions (e.g. memcpy) aren't
|
// just about any time, and leaf functions (e.g. memcpy) aren't
|
||||||
/ required to leave Cosmopolitan's image base register alone.
|
// required to leave Cosmopolitan's image base register alone.
|
||||||
/
|
//
|
||||||
/ @param %edi is the signal number
|
// @param %edi is the signal number
|
||||||
/ @param %rsi will be passed for sigactions
|
// @param %rsi will be passed for sigactions
|
||||||
/ @param %rdx will be passed for sigactions
|
// @param %rdx will be passed for sigactions
|
||||||
/ @return true if handler was invoked
|
// @return true if handler was invoked
|
||||||
__sigenter:
|
__sigenter:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -10,5 +10,8 @@ struct dirent { /* linux getdents64 abi */
|
||||||
char d_name[256]; /* NUL-terminated basename */
|
char d_name[256]; /* NUL-terminated basename */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dirstream;
|
||||||
|
typedef struct dirstream DIR;
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_ */
|
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_ */
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/fmt/itoa.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/nt/console.h"
|
#include "libc/nt/console.h"
|
||||||
#include "libc/nt/enum/consolemodeflags.h"
|
#include "libc/nt/enum/consolemodeflags.h"
|
||||||
|
@ -58,7 +59,7 @@ static int ttyname_linux(int fd, char *buf, size_t size) {
|
||||||
struct stat st1, st2;
|
struct stat st1, st2;
|
||||||
if (!isatty(fd)) return errno;
|
if (!isatty(fd)) return errno;
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
snprintf(name, sizeof(name), "/proc/self/fd/%d", fd);
|
int64toarray_radix10(fd, stpcpy(name, "/proc/self/fd/"));
|
||||||
ssize_t got;
|
ssize_t got;
|
||||||
got = readlink(name, buf, size);
|
got = readlink(name, buf, size);
|
||||||
if (got == -1) return errno;
|
if (got == -1) return errno;
|
||||||
|
|
|
@ -4,7 +4,5 @@
|
||||||
|
|
||||||
typedef void (*sighandler_t)(int);
|
typedef void (*sighandler_t)(int);
|
||||||
|
|
||||||
typedef void (*sighandler_t)(int);
|
|
||||||
|
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_LIBC_CALLS_TYPEDEF_SIGHANDLER_T_H_ */
|
#endif /* COSMOPOLITAN_LIBC_CALLS_TYPEDEF_SIGHANDLER_T_H_ */
|
||||||
|
|
|
@ -23,11 +23,11 @@
|
||||||
.section .start,"ax",@progbits
|
.section .start,"ax",@progbits
|
||||||
.align 16
|
.align 16
|
||||||
|
|
||||||
/ System Five userspace program entrypoint.
|
// System Five userspace program entrypoint.
|
||||||
/
|
//
|
||||||
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
|
// @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
|
||||||
/ @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
|
// @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
|
||||||
/ @noreturn
|
// @noreturn
|
||||||
_start:
|
_start:
|
||||||
#if SupportsFreebsd()
|
#if SupportsFreebsd()
|
||||||
test %rdi,%rdi
|
test %rdi,%rdi
|
||||||
|
@ -39,12 +39,12 @@ _start:
|
||||||
lea 8(%rsp),%rsi # argv
|
lea 8(%rsp),%rsi # argv
|
||||||
lea 24(%rsp,%rbx,8),%rdx # envp
|
lea 24(%rsp,%rbx,8),%rdx # envp
|
||||||
.frame0
|
.frame0
|
||||||
/ bofram 9f
|
// bofram 9f
|
||||||
.weak idata.iat
|
.weak ape_idata_iat
|
||||||
.weak idata.iatend
|
.weak ape_idata_iatend
|
||||||
ezlea missingno,ax # make win32 imps noop
|
ezlea missingno,ax # make win32 imps noop
|
||||||
ezlea idata.iat,di
|
ezlea ape_idata_iat,di
|
||||||
ezlea idata.iatend,cx
|
ezlea ape_idata_iatend,cx
|
||||||
sub %rdi,%rcx
|
sub %rdi,%rcx
|
||||||
shr $3,%ecx
|
shr $3,%ecx
|
||||||
rep stosq
|
rep stosq
|
||||||
|
@ -70,11 +70,11 @@ _start:
|
||||||
.endfn _start,weak,hidden
|
.endfn _start,weak,hidden
|
||||||
|
|
||||||
#if SupportsXnu()
|
#if SupportsXnu()
|
||||||
/ Macintosh userspace program entrypoint.
|
// Macintosh userspace program entrypoint.
|
||||||
/
|
//
|
||||||
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
|
// @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
|
||||||
/ @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
|
// @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
|
||||||
/ @noreturn
|
// @noreturn
|
||||||
_xnu: movb $XNU,__hostos(%rip)
|
_xnu: movb $XNU,__hostos(%rip)
|
||||||
jmp 0b
|
jmp 0b
|
||||||
.endfn _xnu,weak,hidden
|
.endfn _xnu,weak,hidden
|
||||||
|
|
|
@ -13,10 +13,8 @@ struct DnsHeader {
|
||||||
uint16_t arcount; /* additional record count */
|
uint16_t arcount; /* additional record count */
|
||||||
};
|
};
|
||||||
|
|
||||||
int serializednsheader(uint8_t *buf, size_t size,
|
int serializednsheader(uint8_t *, size_t, const struct DnsHeader);
|
||||||
const struct DnsHeader header);
|
int deserializednsheader(struct DnsHeader *, const uint8_t *, size_t);
|
||||||
int deserializednsheader(struct DnsHeader *header, const uint8_t *buf,
|
|
||||||
size_t size);
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -54,7 +54,11 @@ static textwindows noinline char *getnthoststxtpath(char *pathbuf,
|
||||||
* @note yoinking realloc() ensures there's no size limits
|
* @note yoinking realloc() ensures there's no size limits
|
||||||
*/
|
*/
|
||||||
const struct HostsTxt *gethoststxt(void) {
|
const struct HostsTxt *gethoststxt(void) {
|
||||||
struct HostsTxtInitialStaticMemory *init = &g_hoststxt_init;
|
FILE *f;
|
||||||
|
const char *path;
|
||||||
|
char pathbuf[PATH_MAX];
|
||||||
|
struct HostsTxtInitialStaticMemory *init;
|
||||||
|
init = &g_hoststxt_init;
|
||||||
if (!g_hoststxt) {
|
if (!g_hoststxt) {
|
||||||
g_hoststxt = &init->ht;
|
g_hoststxt = &init->ht;
|
||||||
init->ht.entries.n = pushpop(ARRAYLEN(init->entries));
|
init->ht.entries.n = pushpop(ARRAYLEN(init->entries));
|
||||||
|
@ -62,14 +66,12 @@ const struct HostsTxt *gethoststxt(void) {
|
||||||
init->ht.strings.n = pushpop(ARRAYLEN(init->strings));
|
init->ht.strings.n = pushpop(ARRAYLEN(init->strings));
|
||||||
init->ht.strings.p = init->strings;
|
init->ht.strings.p = init->strings;
|
||||||
__cxa_atexit(freehoststxt, &g_hoststxt, NULL);
|
__cxa_atexit(freehoststxt, &g_hoststxt, NULL);
|
||||||
char pathbuf[PATH_MAX];
|
path = "/etc/hosts";
|
||||||
const char *path = "/etc/hosts";
|
|
||||||
if (IsWindows()) {
|
if (IsWindows()) {
|
||||||
path = firstnonnull(getnthoststxtpath(pathbuf, ARRAYLEN(pathbuf)), path);
|
path = firstnonnull(getnthoststxtpath(pathbuf, ARRAYLEN(pathbuf)), path);
|
||||||
}
|
}
|
||||||
FILE *f;
|
|
||||||
if (!(f = fopen(path, "r")) || parsehoststxt(g_hoststxt, f) == -1) {
|
if (!(f = fopen(path, "r")) || parsehoststxt(g_hoststxt, f) == -1) {
|
||||||
if (!IsTiny()) fprintf(stderr, "%s: %s: %m\n", "warning", path);
|
/* TODO(jart): Elevate robustness. */
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
sorthoststxt(g_hoststxt);
|
sorthoststxt(g_hoststxt);
|
||||||
|
|
|
@ -55,7 +55,7 @@ const struct ResolvConf *getresolvconf(void) {
|
||||||
rc = getntnameservers(g_resolvconf);
|
rc = getntnameservers(g_resolvconf);
|
||||||
}
|
}
|
||||||
if (rc == -1 && !IsTiny()) {
|
if (rc == -1 && !IsTiny()) {
|
||||||
fprintf(stderr, "%s: %m\n", "nameserver discovery failed");
|
/* TODO(jart): Elevate robustness. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return g_resolvconf;
|
return g_resolvconf;
|
||||||
|
|
|
@ -18,15 +18,20 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/elf/def.h"
|
#include "libc/elf/def.h"
|
||||||
#include "libc/elf/elf.h"
|
#include "libc/elf/elf.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
|
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
|
||||||
|
char *name;
|
||||||
Elf64_Half i;
|
Elf64_Half i;
|
||||||
Elf64_Shdr *shdr;
|
Elf64_Shdr *shdr;
|
||||||
for (i = elf->e_shnum; i > 0; --i) {
|
for (i = 0; i < elf->e_shnum; ++i) {
|
||||||
if (i - 1 == elf->e_shstrndx) continue;
|
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
|
||||||
shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1);
|
|
||||||
if (shdr->sh_type == SHT_STRTAB) {
|
if (shdr->sh_type == SHT_STRTAB) {
|
||||||
return GetElfSectionAddress(elf, mapsize, shdr);
|
name = GetElfSectionName(elf, mapsize,
|
||||||
|
GetElfSectionHeaderAddress(elf, mapsize, i));
|
||||||
|
if (name && !strcmp(name, ".strtab")) {
|
||||||
|
return GetElfSectionAddress(elf, mapsize, shdr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -17,7 +17,6 @@ COSMOPOLITAN_C_START_
|
||||||
int abs(int) libcesque pureconst;
|
int abs(int) libcesque pureconst;
|
||||||
long labs(long) libcesque pureconst;
|
long labs(long) libcesque pureconst;
|
||||||
long long llabs(long long) libcesque pureconst;
|
long long llabs(long long) libcesque pureconst;
|
||||||
char *ltpcpy(char *, long) paramsnonnull() libcesque nocallback;
|
|
||||||
int llog10(unsigned long) libcesque pureconst;
|
int llog10(unsigned long) libcesque pureconst;
|
||||||
int atoi(const char *) paramsnonnull() libcesque;
|
int atoi(const char *) paramsnonnull() libcesque;
|
||||||
long atol(const char *) paramsnonnull() libcesque;
|
long atol(const char *) paramsnonnull() libcesque;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* @param a needs at least 21 bytes
|
* @param a needs at least 21 bytes
|
||||||
* @return bytes written w/o nul
|
* @return bytes written w/o nul
|
||||||
*/
|
*/
|
||||||
noinline size_t uint64toarray_radix10(uint64_t i, char *a) {
|
noinline size_t uint64toarray_radix10(uint64_t i, char a[hasatleast 21]) {
|
||||||
size_t j;
|
size_t j;
|
||||||
j = 0;
|
j = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -43,7 +43,7 @@ noinline size_t uint64toarray_radix10(uint64_t i, char *a) {
|
||||||
* @param a needs at least 21 bytes
|
* @param a needs at least 21 bytes
|
||||||
* @return bytes written w/o nul
|
* @return bytes written w/o nul
|
||||||
*/
|
*/
|
||||||
size_t int64toarray_radix10(int64_t i, char *a) {
|
size_t int64toarray_radix10(int64_t i, char a[hasatleast 21]) {
|
||||||
if (i >= 0) return uint64toarray_radix10(i, a);
|
if (i >= 0) return uint64toarray_radix10(i, a);
|
||||||
*a++ = '-';
|
*a++ = '-';
|
||||||
return 1 + uint64toarray_radix10(-i, a);
|
return 1 + uint64toarray_radix10(-i, a);
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*-*- mode:c; indent-tabs-mode:nil; tab-width:2; 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/bits/bits.h"
|
|
||||||
#include "libc/fmt/conv.h"
|
|
||||||
|
|
||||||
char *ltpcpy(char *dst, long x) {
|
|
||||||
unsigned len = llog10(abs(x)) + 1;
|
|
||||||
if (x < 0) *dst++ = '-';
|
|
||||||
unsigned i = len;
|
|
||||||
do {
|
|
||||||
dst[--i] = '0' + x % 10;
|
|
||||||
x /= 10;
|
|
||||||
} while (i);
|
|
||||||
return dst + len;
|
|
||||||
}
|
|
|
@ -129,7 +129,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
|
||||||
int w, flags, width, lasterr, precision;
|
int w, flags, width, lasterr, precision;
|
||||||
|
|
||||||
lasterr = errno;
|
lasterr = errno;
|
||||||
out = fn ? fn : (int (*)(int, void *))missingno;
|
out = fn ? fn : (void *)missingno;
|
||||||
|
|
||||||
while (*format) {
|
while (*format) {
|
||||||
/* %[flags][width][.precision][length] */
|
/* %[flags][width][.precision][length] */
|
||||||
|
@ -267,9 +267,8 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
|
||||||
case 'u': {
|
case 'u': {
|
||||||
flags &= ~FLAGS_HASH; /* no hash for dec format */
|
flags &= ~FLAGS_HASH; /* no hash for dec format */
|
||||||
DoNumber:
|
DoNumber:
|
||||||
if (!weaken(ntoa) ||
|
if (ntoa(out, arg, va, signbit, log2base, precision, width, flags,
|
||||||
weaken(ntoa)(out, arg, va, signbit, log2base, precision, width,
|
alphabet) == -1) {
|
||||||
flags, alphabet) == -1) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -282,8 +281,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
|
||||||
} else {
|
} else {
|
||||||
ldbl = va_arg(va, double);
|
ldbl = va_arg(va, double);
|
||||||
}
|
}
|
||||||
if (!weaken(ftoa) ||
|
if (ftoa(out, arg, ldbl, precision, width, flags) == -1) {
|
||||||
weaken(ftoa)(out, arg, ldbl, precision, width, flags) == -1) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -312,8 +310,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
|
||||||
case 's':
|
case 's':
|
||||||
p = va_arg(va, void *);
|
p = va_arg(va, void *);
|
||||||
showstr:
|
showstr:
|
||||||
if (!weaken(stoa) || weaken(stoa)(out, arg, p, flags, precision, width,
|
if (stoa(out, arg, p, flags, precision, width, signbit, qchar) == -1) {
|
||||||
signbit, qchar) == -1) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,22 +17,19 @@
|
||||||
* format strings are constexprs that only contain directives.
|
* format strings are constexprs that only contain directives.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PFLINK(FMT) \
|
#define PFLINK(FMT) \
|
||||||
({ \
|
({ \
|
||||||
if (___PFLINK(FMT, strpbrk, "bxdinupo")) STATIC_YOINK("ntoa"); \
|
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
|
||||||
if (___PFLINK(FMT, strpbrk, "fFgGaA")) STATIC_YOINK("ftoa"); \
|
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
|
||||||
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
|
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
|
||||||
STATIC_YOINK("stoa"); \
|
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
|
||||||
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
|
___PFLINK(FMT, strpbrk, "0123456789"))) { \
|
||||||
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
|
STATIC_YOINK("strnwidth"); \
|
||||||
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
|
STATIC_YOINK("strnwidth16"); \
|
||||||
___PFLINK(FMT, strpbrk, "0123456789"))) { \
|
STATIC_YOINK("wcsnwidth"); \
|
||||||
STATIC_YOINK("strnwidth"); \
|
} \
|
||||||
STATIC_YOINK("strnwidth16"); \
|
} \
|
||||||
STATIC_YOINK("wcsnwidth"); \
|
FMT; \
|
||||||
} \
|
|
||||||
} \
|
|
||||||
FMT; \
|
|
||||||
})
|
})
|
||||||
|
|
||||||
#define SFLINK(FMT) \
|
#define SFLINK(FMT) \
|
||||||
|
@ -40,7 +37,7 @@
|
||||||
if (___PFLINK(FMT, strchr, 'm')) { \
|
if (___PFLINK(FMT, strchr, 'm')) { \
|
||||||
STATIC_YOINK("malloc"); \
|
STATIC_YOINK("malloc"); \
|
||||||
STATIC_YOINK("calloc"); \
|
STATIC_YOINK("calloc"); \
|
||||||
STATIC_YOINK("free_s"); \
|
STATIC_YOINK("free"); \
|
||||||
STATIC_YOINK("__grow"); \
|
STATIC_YOINK("__grow"); \
|
||||||
} \
|
} \
|
||||||
FMT; \
|
FMT; \
|
||||||
|
@ -70,8 +67,6 @@
|
||||||
#define SFLINK(FMT) FMT
|
#define SFLINK(FMT) FMT
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
__asm__(".section .yoink\n\t"
|
__asm__(".section .yoink\n\t"
|
||||||
"nopl\tntoa(%rip)\n\t"
|
|
||||||
"nopl\tftoa(%rip)\n\t"
|
|
||||||
"nopl\tkCp437(%rip)\n\t"
|
"nopl\tkCp437(%rip)\n\t"
|
||||||
"nopl\tstrerror(%rip)\n\t"
|
"nopl\tstrerror(%rip)\n\t"
|
||||||
"nopl\tstrnwidth(%rip)\n\t"
|
"nopl\tstrnwidth(%rip)\n\t"
|
||||||
|
@ -79,14 +74,11 @@ __asm__(".section .yoink\n\t"
|
||||||
"nopl\twcsnwidth(%rip)\n\t"
|
"nopl\twcsnwidth(%rip)\n\t"
|
||||||
"nopl\tmalloc(%rip)\n\t"
|
"nopl\tmalloc(%rip)\n\t"
|
||||||
"nopl\tcalloc(%rip)\n\t"
|
"nopl\tcalloc(%rip)\n\t"
|
||||||
"nopl\tfree_s(%rip)\n\t"
|
|
||||||
"nopl\t__grow(%rip)\n\t"
|
"nopl\t__grow(%rip)\n\t"
|
||||||
".previous");
|
".previous");
|
||||||
#else
|
#else
|
||||||
static long __pflink(long x) {
|
static long __pflink(long x) {
|
||||||
x |= kCp437[0];
|
x |= kCp437[0];
|
||||||
x |= ntoa(0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
||||||
x |= ftoa(0, 0, 0, 0, 0, 0);
|
|
||||||
x |= strnwidth(0, 0, 0);
|
x |= strnwidth(0, 0, 0);
|
||||||
x |= strnwidth16(0, 0, 0);
|
x |= strnwidth16(0, 0, 0);
|
||||||
x |= wcsnwidth(0, 0, 0);
|
x |= wcsnwidth(0, 0, 0);
|
||||||
|
@ -94,7 +86,6 @@ static long __pflink(long x) {
|
||||||
x |= __grow(0, 0, 0, 0);
|
x |= __grow(0, 0, 0, 0);
|
||||||
x |= (intptr_t)strerror(0);
|
x |= (intptr_t)strerror(0);
|
||||||
x |= (intptr_t)calloc(0, 0);
|
x |= (intptr_t)calloc(0, 0);
|
||||||
free_s(0);
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
STATIC_YOINK("ntoa");
|
||||||
|
STATIC_YOINK("stoa");
|
||||||
|
|
||||||
STATIC_YOINK("E2BIG");
|
STATIC_YOINK("E2BIG");
|
||||||
STATIC_YOINK("EACCES");
|
STATIC_YOINK("EACCES");
|
||||||
STATIC_YOINK("EADDRINUSE");
|
STATIC_YOINK("EADDRINUSE");
|
||||||
|
@ -321,7 +324,7 @@ int strerror_r(int err, char *buf, size_t size) {
|
||||||
s = firstnonnull(geterrname(err), "?");
|
s = firstnonnull(geterrname(err), "?");
|
||||||
}
|
}
|
||||||
if (!SupportsWindows()) {
|
if (!SupportsWindows()) {
|
||||||
snprintf(buf, size, "E%s[%d]", s, err);
|
(snprintf)(buf, size, "E%s[%d]", s, err);
|
||||||
} else {
|
} else {
|
||||||
winstate = GetLastError();
|
winstate = GetLastError();
|
||||||
sysvstate = errno;
|
sysvstate = errno;
|
||||||
|
@ -332,8 +335,8 @@ int strerror_r(int err, char *buf, size_t size) {
|
||||||
} else {
|
} else {
|
||||||
buf16[0] = u'\0';
|
buf16[0] = u'\0';
|
||||||
}
|
}
|
||||||
snprintf(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
|
(snprintf)(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
|
||||||
sysvstate, winstate, buf16[0] ? " " : "", buf16);
|
sysvstate, winstate, buf16[0] ? " " : "", buf16);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,13 +286,11 @@ int vcscanf(int callback(void *), int unget(int, void *), void *arg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Done:
|
Done:
|
||||||
while (freeme) {
|
while (freeme && weaken(free)) {
|
||||||
struct FreeMe *entry = freeme;
|
struct FreeMe *entry = freeme;
|
||||||
freeme = entry->next;
|
freeme = entry->next;
|
||||||
if (items == -1) {
|
if (items == -1) weaken(free)(entry->ptr);
|
||||||
weaken(free_s)((void **)&entry->ptr);
|
weaken(free)(entry);
|
||||||
}
|
|
||||||
weaken(free_s)((void **)&entry);
|
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,22 +67,6 @@
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDC_VERSION__ + 0 < 201112
|
|
||||||
#define ____Static_assert(x, y) A##B
|
|
||||||
#define ___Static_assert(x, y) ____Static_assert(x, y)
|
|
||||||
#ifndef __cplusplus /* todo jart what */
|
|
||||||
#define __Static_assert(x) __builtin_choose_expr(__builtin_constant_p(x), x, 1)
|
|
||||||
#else
|
|
||||||
#define __Static_assert(x) (x)
|
|
||||||
#endif
|
|
||||||
#define _Static_assert(x, s) /* clang-format off */ do { \
|
|
||||||
__builtin_assume(x); \
|
|
||||||
enum { ___Static_assert(_Assert, __COUNTER__) = \
|
|
||||||
1 / !!__Static_assert(x) \
|
|
||||||
} /*_Unused*/; /* clang-format on */ \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __STDC_VERSION__ + 0 < 201112 && defined(__x86__)
|
#if __STDC_VERSION__ + 0 < 201112 && defined(__x86__)
|
||||||
#define _Atomic(TYPE) TYPE
|
#define _Atomic(TYPE) TYPE
|
||||||
#endif
|
#endif
|
||||||
|
@ -652,7 +636,7 @@ typedef uint64_t uintmax_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _Section
|
#ifndef _Section
|
||||||
#ifndef __STRICT_ANSI__
|
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
|
||||||
#define _Section(s) __attribute__((__section__(s)))
|
#define _Section(s) __attribute__((__section__(s)))
|
||||||
#else
|
#else
|
||||||
#define _Section(s)
|
#define _Section(s)
|
||||||
|
@ -667,16 +651,17 @@ typedef uint64_t uintmax_t;
|
||||||
|
|
||||||
#ifndef __STRICT_ANSI__
|
#ifndef __STRICT_ANSI__
|
||||||
#if defined(__GNUC__) || defined(__llvm__)
|
#if defined(__GNUC__) || defined(__llvm__)
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
|
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
|
||||||
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
|
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
|
||||||
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
|
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
|
||||||
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
|
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
|
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
|
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
|
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
|
||||||
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* is also broken */
|
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* is also broken */
|
||||||
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
|
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
|
||||||
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
|
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
|
||||||
|
#pragma GCC diagnostic ignored "-Wformat-security" /* come on tidy */
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
#pragma GCC diagnostic ignored "-Wimplicit-int"
|
#pragma GCC diagnostic ignored "-Wimplicit-int"
|
||||||
#endif /* C++ */
|
#endif /* C++ */
|
||||||
|
@ -704,8 +689,8 @@ typedef uint64_t uintmax_t;
|
||||||
"-Wincompatible-pointer-types-discards-qualifiers"
|
"-Wincompatible-pointer-types-discards-qualifiers"
|
||||||
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
|
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
|
||||||
#pragma clang diagnostic ignored "-Wparentheses-equality" /*-save-temps*/
|
#pragma clang diagnostic ignored "-Wparentheses-equality" /*-save-temps*/
|
||||||
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
|
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
|
||||||
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
|
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
|
||||||
#pragma clang diagnostic ignored "-Wunused-value" /* extreme prejudice */
|
#pragma clang diagnostic ignored "-Wunused-value" /* extreme prejudice */
|
||||||
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
|
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
|
||||||
#pragma clang diagnostic ignored \
|
#pragma clang diagnostic ignored \
|
||||||
|
@ -797,22 +782,14 @@ typedef uint64_t uintmax_t;
|
||||||
#define EXPROPRIATE(EXPRESSION) (EXPRESSION)
|
#define EXPROPRIATE(EXPRESSION) (EXPRESSION)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __STRICT_ANSI__
|
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
|
||||||
#define YOINK(SYMBOL) \
|
#define YOINK(SYMBOL) \
|
||||||
do { \
|
asm(".section .yoink\n\tnopl\t%a0\n\t.previous" : : "X"(SYMBOL))
|
||||||
_Static_assert(!__builtin_types_compatible_p(typeof(SYMBOL), char[]), \
|
|
||||||
"Please YOINK(symbol), not YOINK(\"symbol\")"); \
|
|
||||||
asm(".section .yoink\n\t" \
|
|
||||||
"nop\t%a0\n\t" \
|
|
||||||
".previous" \
|
|
||||||
: /* no outputs */ \
|
|
||||||
: "X"(SYMBOL)); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
#else
|
||||||
#define YOINK(SYMBOL) (void)0
|
#define YOINK(SYMBOL) (void)0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __STRICT_ANSI__
|
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
|
||||||
#define STATIC_YOINK(SYMBOLSTR) \
|
#define STATIC_YOINK(SYMBOLSTR) \
|
||||||
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
|
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥+𝑦, aborting on overflow.
|
// Returns 𝑥+𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi is int64 𝑥
|
// @param rdi is int64 𝑥
|
||||||
/ @param rsi is int64 𝑦
|
// @param rsi is int64 𝑦
|
||||||
/ @return rax is 𝑥+𝑦
|
// @return rax is 𝑥+𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__addvdi3:
|
__addvdi3:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
add %rsi,%rax
|
add %rsi,%rax
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥+𝑦, aborting on overflow.
|
// Returns 𝑥+𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param edi is int32 𝑥
|
// @param edi is int32 𝑥
|
||||||
/ @param esi is int32 𝑦
|
// @param esi is int32 𝑦
|
||||||
/ @return eax is 𝑥+𝑦
|
// @return eax is 𝑥+𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__addvsi3:
|
__addvsi3:
|
||||||
mov %edi,%eax
|
mov %edi,%eax
|
||||||
add %esi,%eax
|
add %esi,%eax
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥+𝑦, aborting on overflow.
|
// Returns 𝑥+𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi:rsi is int128 𝑥
|
// @param rdi:rsi is int128 𝑥
|
||||||
/ @param rdx:rcx is int128 𝑦
|
// @param rdx:rcx is int128 𝑦
|
||||||
/ @return rdx:rax is 𝑥+𝑦
|
// @return rdx:rax is 𝑥+𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__addvti3:
|
__addvti3:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
add %rdx,%rax
|
add %rdx,%rax
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Jump table for mpsadbw() with non-constexpr immediate parameter.
|
// Jump table for mpsadbw() with non-constexpr immediate parameter.
|
||||||
/
|
//
|
||||||
/ @note needs sse4 cf. core c. 2006 cf. bulldozer c. 2011
|
// @note needs sse4 cf. core c. 2006 cf. bulldozer c. 2011
|
||||||
/ @see mpsadbw()
|
// @see mpsadbw()
|
||||||
.align 8
|
.align 8
|
||||||
__mpsadbws:
|
__mpsadbws:
|
||||||
i = 0
|
i = 0
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥*𝑦, aborting on overflow.
|
// Returns 𝑥*𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi is int64 𝑥
|
// @param rdi is int64 𝑥
|
||||||
/ @param rdi is int64 𝑦
|
// @param rdi is int64 𝑦
|
||||||
/ @return rax is 𝑥*𝑦
|
// @return rax is 𝑥*𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__mulvdi3:
|
__mulvdi3:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
imul %rsi
|
imul %rsi
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥*𝑦, aborting on overflow.
|
// Returns 𝑥*𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param edi is int32 𝑥
|
// @param edi is int32 𝑥
|
||||||
/ @param esi is int32 𝑦
|
// @param esi is int32 𝑦
|
||||||
/ @return eax is 𝑥*𝑦
|
// @return eax is 𝑥*𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__mulvsi3:
|
__mulvsi3:
|
||||||
mov %edi,%eax
|
mov %edi,%eax
|
||||||
imul %esi
|
imul %esi
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥*𝑦, aborting on overflow.
|
// Returns 𝑥*𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi:rsi is int128 𝑥
|
// @param rdi:rsi is int128 𝑥
|
||||||
/ @param rdx:rcx is int128 𝑦
|
// @param rdx:rcx is int128 𝑦
|
||||||
/ @return rdx:rax is 𝑥*𝑦
|
// @return rdx:rax is 𝑥*𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__mulvti3:
|
__mulvti3:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns -𝑥, aborting on overflow (two's complement bane).
|
// Returns -𝑥, aborting on overflow (two's complement bane).
|
||||||
/
|
//
|
||||||
/ @param rdi is int64 𝑥
|
// @param rdi is int64 𝑥
|
||||||
/ @return rax is -𝑥
|
// @return rax is -𝑥
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__negvdi2:
|
__negvdi2:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
neg %rax
|
neg %rax
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns -𝑥, aborting on overflow (two's complement bane).
|
// Returns -𝑥, aborting on overflow (two's complement bane).
|
||||||
/
|
//
|
||||||
/ @param edi is int32 𝑥
|
// @param edi is int32 𝑥
|
||||||
/ @return eax is -𝑥
|
// @return eax is -𝑥
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__negvsi2:
|
__negvsi2:
|
||||||
mov %edi,%eax
|
mov %edi,%eax
|
||||||
neg %eax
|
neg %eax
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns -𝑥, aborting on overflow.
|
// Returns -𝑥, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi:rsi is int128 𝑥
|
// @param rdi:rsi is int128 𝑥
|
||||||
/ @return rdx:rax is -𝑥
|
// @return rdx:rax is -𝑥
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__negvti2:
|
__negvti2:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
mov %rsi,%rdx
|
mov %rsi,%rdx
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
.privileged
|
.privileged
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Arithmetic overflow handler.
|
// Arithmetic overflow handler.
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__on_arithmetic_overflow:
|
__on_arithmetic_overflow:
|
||||||
push %rbp
|
push %rbp
|
||||||
mov %rsp,%rbp
|
mov %rsp,%rbp
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Jump table for palignr() with non-constexpr immediate parameter.
|
// Jump table for palignr() with non-constexpr immediate parameter.
|
||||||
/
|
//
|
||||||
/ @note needs ssse3 cf. prescott c. 2004 cf. bulldozer c. 2011
|
// @note needs ssse3 cf. prescott c. 2004 cf. bulldozer c. 2011
|
||||||
/ @see palignr()
|
// @see palignr()
|
||||||
.align 8
|
.align 8
|
||||||
__palignrs:
|
__palignrs:
|
||||||
palignr $0,%xmm1,%xmm0
|
palignr $0,%xmm1,%xmm0
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Jump table for pslldq() with non-constexpr immediate parameter.
|
// Jump table for pslldq() with non-constexpr immediate parameter.
|
||||||
.align 8
|
.align 8
|
||||||
__pslldqs:
|
__pslldqs:
|
||||||
pslldq $0,%xmm0
|
pslldq $0,%xmm0
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
/ Jump table for psrldq() with non-constexpr immediate parameter.
|
// Jump table for psrldq() with non-constexpr immediate parameter.
|
||||||
.align 8
|
.align 8
|
||||||
__psrldqs:
|
__psrldqs:
|
||||||
psrldq $0,%xmm0
|
psrldq $0,%xmm0
|
||||||
|
|
|
@ -53,11 +53,11 @@ __asan_report_load16:
|
||||||
.endfn __asan_report_load16,globl
|
.endfn __asan_report_load16,globl
|
||||||
__asan_report_load32:
|
__asan_report_load32:
|
||||||
push $32
|
push $32
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_report_load32,globl
|
.endfn __asan_report_load32,globl
|
||||||
OnReportLoad:
|
OnReportLoad:
|
||||||
pop %rsi
|
pop %rsi
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn OnReportLoad
|
.endfn OnReportLoad
|
||||||
__asan_report_load_n:
|
__asan_report_load_n:
|
||||||
lea __asan_report_load(%rip),%r11
|
lea __asan_report_load(%rip),%r11
|
||||||
|
@ -86,15 +86,15 @@ __asan_report_store16:
|
||||||
.endfn __asan_report_store16,globl
|
.endfn __asan_report_store16,globl
|
||||||
__asan_report_store32:
|
__asan_report_store32:
|
||||||
push $32
|
push $32
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_report_store32,globl
|
.endfn __asan_report_store32,globl
|
||||||
ReportStore:
|
ReportStore:
|
||||||
pop %rsi
|
pop %rsi
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn ReportStore
|
.endfn ReportStore
|
||||||
__asan_report_store_n:
|
__asan_report_store_n:
|
||||||
lea __asan_report_store(%rip),%r11
|
lea __asan_report_store(%rip),%r11
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_report_store_n,globl
|
.endfn __asan_report_store_n,globl
|
||||||
|
|
||||||
__asan_report_noreentry:
|
__asan_report_noreentry:
|
||||||
|
@ -152,7 +152,7 @@ __asan_stack_free_9:
|
||||||
.endfn __asan_stack_free_9,globl
|
.endfn __asan_stack_free_9,globl
|
||||||
__asan_stack_free_10:
|
__asan_stack_free_10:
|
||||||
push $10
|
push $10
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_stack_free_10,globl
|
.endfn __asan_stack_free_10,globl
|
||||||
OnStackFree:
|
OnStackFree:
|
||||||
pop %rdx
|
pop %rdx
|
||||||
|
@ -201,7 +201,7 @@ __asan_stack_malloc_9:
|
||||||
.endfn __asan_stack_malloc_9,globl
|
.endfn __asan_stack_malloc_9,globl
|
||||||
__asan_stack_malloc_10:
|
__asan_stack_malloc_10:
|
||||||
push $10
|
push $10
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_stack_malloc_10,globl
|
.endfn __asan_stack_malloc_10,globl
|
||||||
OnStackMalloc:
|
OnStackMalloc:
|
||||||
pop %rsi
|
pop %rsi
|
||||||
|
@ -212,7 +212,7 @@ __asan_version_mismatch_check_v8:
|
||||||
ret
|
ret
|
||||||
.endfn __asan_version_mismatch_check_v8,globl
|
.endfn __asan_version_mismatch_check_v8,globl
|
||||||
|
|
||||||
/ Initializes Address Sanitizer runtime earlier if linked.
|
// Initializes Address Sanitizer runtime earlier if linked.
|
||||||
.init.start 301,_init_asan
|
.init.start 301,_init_asan
|
||||||
push %rdi
|
push %rdi
|
||||||
push %rsi
|
push %rsi
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥-𝑦, aborting on overflow.
|
// Returns 𝑥-𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi is int64 𝑥
|
// @param rdi is int64 𝑥
|
||||||
/ @param rsi is int64 𝑦
|
// @param rsi is int64 𝑦
|
||||||
/ @return rax is 𝑥-𝑦
|
// @return rax is 𝑥-𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__subvdi3:
|
__subvdi3:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
sub %rsi,%rax
|
sub %rsi,%rax
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥-𝑦, aborting on overflow.
|
// Returns 𝑥-𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param edi is int32 𝑥
|
// @param edi is int32 𝑥
|
||||||
/ @param esi is int32 𝑦
|
// @param esi is int32 𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__subvsi3:
|
__subvsi3:
|
||||||
mov %edi,%eax
|
mov %edi,%eax
|
||||||
sub %esi,%eax
|
sub %esi,%eax
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.alignfunc
|
.alignfunc
|
||||||
|
|
||||||
/ Returns 𝑥-𝑦, aborting on overflow.
|
// Returns 𝑥-𝑦, aborting on overflow.
|
||||||
/
|
//
|
||||||
/ @param rdi:rsi is int128 𝑥
|
// @param rdi:rsi is int128 𝑥
|
||||||
/ @param rdx:rcx is int128 𝑦
|
// @param rdx:rcx is int128 𝑦
|
||||||
/ @return rdx:rax is 𝑥-𝑦
|
// @return rdx:rax is 𝑥-𝑦
|
||||||
/ @see -ftrapv
|
// @see -ftrapv
|
||||||
__subvti3:
|
__subvti3:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
sub %rdx,%rax
|
sub %rdx,%rax
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_LOG_LOG_H_
|
#ifndef COSMOPOLITAN_LIBC_LOG_LOG_H_
|
||||||
#define COSMOPOLITAN_LIBC_LOG_LOG_H_
|
#define COSMOPOLITAN_LIBC_LOG_LOG_H_
|
||||||
|
#include "libc/calls/struct/sigset.h"
|
||||||
|
#include "libc/calls/struct/winsize.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § liblog ─╬─│┼
|
│ cosmopolitan § liblog ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
#define kLogFatal 0u
|
#define kLogFatal 0
|
||||||
#define kLogError 1u
|
#define kLogError 1
|
||||||
#define kLogWarn 2u
|
#define kLogWarn 2
|
||||||
#define kLogInfo 3u
|
#define kLogInfo 3
|
||||||
#define kLogVerbose 4u
|
#define kLogVerbose 4
|
||||||
#define kLogDebug 5u
|
#define kLogDebug 5
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log level for compile-time DCE.
|
* Log level for compile-time DCE.
|
||||||
|
@ -27,10 +30,6 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
struct sigset;
|
|
||||||
struct winsize;
|
|
||||||
typedef struct FILE FILE;
|
|
||||||
|
|
||||||
extern FILE *g_logfile;
|
extern FILE *g_logfile;
|
||||||
|
|
||||||
void perror(const char *) relegated; /* print the last system error */
|
void perror(const char *) relegated; /* print the last system error */
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ These function names make it a bit more obvious which signal
|
// These function names make it a bit more obvious which signal
|
||||||
/ caused the crash, particularly in the GDB GUI. They're coded
|
// caused the crash, particularly in the GDB GUI. They're coded
|
||||||
/ into an array to pinch pennies on code size registering them.
|
// into an array to pinch pennies on code size registering them.
|
||||||
|
|
||||||
__oncrash_thunks:
|
__oncrash_thunks:
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ __ubsan_handle_type_mismatch_v1_abort:
|
||||||
|
|
||||||
__ubsan_handle_add_overflow_abort:
|
__ubsan_handle_add_overflow_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_add_overflow_abort,globl
|
.endfn __ubsan_handle_add_overflow_abort,globl
|
||||||
__ubsan_handle_add_overflow:
|
__ubsan_handle_add_overflow:
|
||||||
loadstr "add_overflow",si
|
loadstr "add_overflow",si
|
||||||
|
@ -58,7 +58,7 @@ __ubsan_handle_add_overflow:
|
||||||
|
|
||||||
__ubsan_handle_alignment_assumption_abort:
|
__ubsan_handle_alignment_assumption_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_alignment_assumption_abort,globl
|
.endfn __ubsan_handle_alignment_assumption_abort,globl
|
||||||
__ubsan_handle_alignment_assumption:
|
__ubsan_handle_alignment_assumption:
|
||||||
loadstr "alignment_assumption",si
|
loadstr "alignment_assumption",si
|
||||||
|
@ -67,7 +67,7 @@ __ubsan_handle_alignment_assumption:
|
||||||
|
|
||||||
__ubsan_handle_builtin_unreachable_abort:
|
__ubsan_handle_builtin_unreachable_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_builtin_unreachable_abort,globl
|
.endfn __ubsan_handle_builtin_unreachable_abort,globl
|
||||||
__ubsan_handle_builtin_unreachable:
|
__ubsan_handle_builtin_unreachable:
|
||||||
loadstr "builtin_unreachable",si
|
loadstr "builtin_unreachable",si
|
||||||
|
@ -76,7 +76,7 @@ __ubsan_handle_builtin_unreachable:
|
||||||
|
|
||||||
__ubsan_handle_cfi_bad_type_abort:
|
__ubsan_handle_cfi_bad_type_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_cfi_bad_type_abort,globl
|
.endfn __ubsan_handle_cfi_bad_type_abort,globl
|
||||||
__ubsan_handle_cfi_bad_type:
|
__ubsan_handle_cfi_bad_type:
|
||||||
loadstr "cfi_bad_type",si
|
loadstr "cfi_bad_type",si
|
||||||
|
@ -85,7 +85,7 @@ __ubsan_handle_cfi_bad_type:
|
||||||
|
|
||||||
__ubsan_handle_cfi_check_fail_abort:
|
__ubsan_handle_cfi_check_fail_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_cfi_check_fail_abort,globl
|
.endfn __ubsan_handle_cfi_check_fail_abort,globl
|
||||||
__ubsan_handle_cfi_check_fail:
|
__ubsan_handle_cfi_check_fail:
|
||||||
loadstr "cfi_check_fail",si
|
loadstr "cfi_check_fail",si
|
||||||
|
@ -94,7 +94,7 @@ __ubsan_handle_cfi_check_fail:
|
||||||
|
|
||||||
__ubsan_handle_divrem_overflow_abort:
|
__ubsan_handle_divrem_overflow_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_divrem_overflow_abort,globl
|
.endfn __ubsan_handle_divrem_overflow_abort,globl
|
||||||
__ubsan_handle_divrem_overflow:
|
__ubsan_handle_divrem_overflow:
|
||||||
loadstr "divrem_overflow",si
|
loadstr "divrem_overflow",si
|
||||||
|
@ -103,7 +103,7 @@ __ubsan_handle_divrem_overflow:
|
||||||
|
|
||||||
__ubsan_handle_dynamic_type_cache_miss_abort:
|
__ubsan_handle_dynamic_type_cache_miss_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,globl
|
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,globl
|
||||||
__ubsan_handle_dynamic_type_cache_miss:
|
__ubsan_handle_dynamic_type_cache_miss:
|
||||||
loadstr "dynamic_type_cache_miss",si
|
loadstr "dynamic_type_cache_miss",si
|
||||||
|
@ -112,7 +112,7 @@ __ubsan_handle_dynamic_type_cache_miss:
|
||||||
|
|
||||||
__ubsan_handle_function_type_mismatch_abort:
|
__ubsan_handle_function_type_mismatch_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_function_type_mismatch_abort,globl
|
.endfn __ubsan_handle_function_type_mismatch_abort,globl
|
||||||
__ubsan_handle_function_type_mismatch:
|
__ubsan_handle_function_type_mismatch:
|
||||||
loadstr "function_type_mismatch",si
|
loadstr "function_type_mismatch",si
|
||||||
|
@ -121,7 +121,7 @@ __ubsan_handle_function_type_mismatch:
|
||||||
|
|
||||||
__ubsan_handle_implicit_conversion_abort:
|
__ubsan_handle_implicit_conversion_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_implicit_conversion_abort,globl
|
.endfn __ubsan_handle_implicit_conversion_abort,globl
|
||||||
__ubsan_handle_implicit_conversion:
|
__ubsan_handle_implicit_conversion:
|
||||||
loadstr "implicit_conversion",si
|
loadstr "implicit_conversion",si
|
||||||
|
@ -130,7 +130,7 @@ __ubsan_handle_implicit_conversion:
|
||||||
|
|
||||||
__ubsan_handle_invalid_builtin_abort:
|
__ubsan_handle_invalid_builtin_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_invalid_builtin_abort,globl
|
.endfn __ubsan_handle_invalid_builtin_abort,globl
|
||||||
__ubsan_handle_invalid_builtin:
|
__ubsan_handle_invalid_builtin:
|
||||||
loadstr "invalid_builtin",si
|
loadstr "invalid_builtin",si
|
||||||
|
@ -139,7 +139,7 @@ __ubsan_handle_invalid_builtin:
|
||||||
|
|
||||||
__ubsan_handle_load_invalid_value_abort:
|
__ubsan_handle_load_invalid_value_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_load_invalid_value_abort,globl
|
.endfn __ubsan_handle_load_invalid_value_abort,globl
|
||||||
__ubsan_handle_load_invalid_value:
|
__ubsan_handle_load_invalid_value:
|
||||||
loadstr "load_invalid_value (try checking for uninitialized variables)",si
|
loadstr "load_invalid_value (try checking for uninitialized variables)",si
|
||||||
|
@ -148,7 +148,7 @@ __ubsan_handle_load_invalid_value:
|
||||||
|
|
||||||
__ubsan_handle_missing_return_abort:
|
__ubsan_handle_missing_return_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_missing_return_abort,globl
|
.endfn __ubsan_handle_missing_return_abort,globl
|
||||||
__ubsan_handle_missing_return:
|
__ubsan_handle_missing_return:
|
||||||
loadstr "missing_return",si
|
loadstr "missing_return",si
|
||||||
|
@ -157,7 +157,7 @@ __ubsan_handle_missing_return:
|
||||||
|
|
||||||
__ubsan_handle_mul_overflow_abort:
|
__ubsan_handle_mul_overflow_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_mul_overflow_abort,globl
|
.endfn __ubsan_handle_mul_overflow_abort,globl
|
||||||
__ubsan_handle_mul_overflow:
|
__ubsan_handle_mul_overflow:
|
||||||
loadstr "mul_overflow",si
|
loadstr "mul_overflow",si
|
||||||
|
@ -166,7 +166,7 @@ __ubsan_handle_mul_overflow:
|
||||||
|
|
||||||
__ubsan_handle_negate_overflow_abort:
|
__ubsan_handle_negate_overflow_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_negate_overflow_abort,globl
|
.endfn __ubsan_handle_negate_overflow_abort,globl
|
||||||
__ubsan_handle_negate_overflow:
|
__ubsan_handle_negate_overflow:
|
||||||
loadstr "negate_overflow",si
|
loadstr "negate_overflow",si
|
||||||
|
@ -175,7 +175,7 @@ __ubsan_handle_negate_overflow:
|
||||||
|
|
||||||
__ubsan_handle_nonnull_arg_abort:
|
__ubsan_handle_nonnull_arg_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_nonnull_arg_abort,globl
|
.endfn __ubsan_handle_nonnull_arg_abort,globl
|
||||||
__ubsan_handle_nonnull_arg:
|
__ubsan_handle_nonnull_arg:
|
||||||
loadstr "nonnull_arg",si
|
loadstr "nonnull_arg",si
|
||||||
|
@ -184,7 +184,7 @@ __ubsan_handle_nonnull_arg:
|
||||||
|
|
||||||
__ubsan_handle_nonnull_return_v1_abort:
|
__ubsan_handle_nonnull_return_v1_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
|
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
|
||||||
__ubsan_handle_nonnull_return_v1:
|
__ubsan_handle_nonnull_return_v1:
|
||||||
loadstr "nonnull_return_v1",si
|
loadstr "nonnull_return_v1",si
|
||||||
|
@ -197,7 +197,7 @@ __ubsan_hop:
|
||||||
|
|
||||||
__ubsan_handle_nullability_arg_abort:
|
__ubsan_handle_nullability_arg_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_nullability_arg_abort,globl
|
.endfn __ubsan_handle_nullability_arg_abort,globl
|
||||||
__ubsan_handle_nullability_arg:
|
__ubsan_handle_nullability_arg:
|
||||||
loadstr "nullability_arg",si
|
loadstr "nullability_arg",si
|
||||||
|
@ -206,7 +206,7 @@ __ubsan_handle_nullability_arg:
|
||||||
|
|
||||||
__ubsan_handle_nullability_return_v1_abort:
|
__ubsan_handle_nullability_return_v1_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_nullability_return_v1_abort,globl
|
.endfn __ubsan_handle_nullability_return_v1_abort,globl
|
||||||
__ubsan_handle_nullability_return_v1:
|
__ubsan_handle_nullability_return_v1:
|
||||||
loadstr "nullability_return_v1",si
|
loadstr "nullability_return_v1",si
|
||||||
|
@ -215,7 +215,7 @@ __ubsan_handle_nullability_return_v1:
|
||||||
|
|
||||||
__ubsan_handle_pointer_overflow_abort:
|
__ubsan_handle_pointer_overflow_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_pointer_overflow_abort,globl
|
.endfn __ubsan_handle_pointer_overflow_abort,globl
|
||||||
__ubsan_handle_pointer_overflow:
|
__ubsan_handle_pointer_overflow:
|
||||||
loadstr "pointer_overflow",si
|
loadstr "pointer_overflow",si
|
||||||
|
@ -224,7 +224,7 @@ __ubsan_handle_pointer_overflow:
|
||||||
|
|
||||||
__ubsan_handle_shift_out_of_bounds_abort:
|
__ubsan_handle_shift_out_of_bounds_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_shift_out_of_bounds_abort,globl
|
.endfn __ubsan_handle_shift_out_of_bounds_abort,globl
|
||||||
__ubsan_handle_shift_out_of_bounds:
|
__ubsan_handle_shift_out_of_bounds:
|
||||||
loadstr "shift_out_of_bounds",si
|
loadstr "shift_out_of_bounds",si
|
||||||
|
@ -233,7 +233,7 @@ __ubsan_handle_shift_out_of_bounds:
|
||||||
|
|
||||||
__ubsan_handle_sub_overflow_abort:
|
__ubsan_handle_sub_overflow_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_sub_overflow_abort,globl
|
.endfn __ubsan_handle_sub_overflow_abort,globl
|
||||||
__ubsan_handle_sub_overflow:
|
__ubsan_handle_sub_overflow:
|
||||||
loadstr "sub_overflow",si
|
loadstr "sub_overflow",si
|
||||||
|
@ -242,7 +242,7 @@ __ubsan_handle_sub_overflow:
|
||||||
|
|
||||||
__ubsan_handle_vla_bound_not_positive_abort:
|
__ubsan_handle_vla_bound_not_positive_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_vla_bound_not_positive_abort,globl
|
.endfn __ubsan_handle_vla_bound_not_positive_abort,globl
|
||||||
__ubsan_handle_vla_bound_not_positive:
|
__ubsan_handle_vla_bound_not_positive:
|
||||||
loadstr "vla_bound_not_positive",si
|
loadstr "vla_bound_not_positive",si
|
||||||
|
@ -251,7 +251,7 @@ __ubsan_handle_vla_bound_not_positive:
|
||||||
|
|
||||||
__ubsan_handle_nonnull_return_abort:
|
__ubsan_handle_nonnull_return_abort:
|
||||||
nop
|
nop
|
||||||
/ fallthrough
|
// fallthrough
|
||||||
.endfn __ubsan_handle_nonnull_return_abort,globl
|
.endfn __ubsan_handle_nonnull_return_abort,globl
|
||||||
__ubsan_handle_nonnull_return:
|
__ubsan_handle_nonnull_return:
|
||||||
loadstr "nonnull_return",si
|
loadstr "nonnull_return",si
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.text.unlikely
|
.text.unlikely
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
|
||||||
__check_fail_eq:
|
__check_fail_eq:
|
||||||
loadstr "==",dx
|
loadstr "==",dx
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.text.unlikely
|
.text.unlikely
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Code-size saving thunk for CHECK_GE() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_GE() in NDEBUG mode.
|
||||||
__check_fail_ge:
|
__check_fail_ge:
|
||||||
loadstr ">=",dx
|
loadstr ">=",dx
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.text.unlikely
|
.text.unlikely
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Code-size saving thunk for CHECK_GT() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_GT() in NDEBUG mode.
|
||||||
__check_fail_gt:
|
__check_fail_gt:
|
||||||
loadstr ">",dx
|
loadstr ">",dx
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.text.unlikely
|
.text.unlikely
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Code-size saving thunk for CHECK_LE() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_LE() in NDEBUG mode.
|
||||||
__check_fail_le:
|
__check_fail_le:
|
||||||
loadstr "<=",dx
|
loadstr "<=",dx
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.text.unlikely
|
.text.unlikely
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Code-size saving thunk for CHECK_LT() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_LT() in NDEBUG mode.
|
||||||
__check_fail_lt:
|
__check_fail_lt:
|
||||||
loadstr "<",dx
|
loadstr "<",dx
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
.text.unlikely
|
.text.unlikely
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Code-size saving thunk for CHECK_NE() in NDEBUG mode.
|
// Code-size saving thunk for CHECK_NE() in NDEBUG mode.
|
||||||
__check_fail_ne:
|
__check_fail_ne:
|
||||||
loadstr "!=",dx
|
loadstr "!=",dx
|
||||||
jmp __check_fail_ndebug
|
jmp __check_fail_ndebug
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#define vzeroupper
|
#define vzeroupper
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/ Begins definition of frameless function that calls no functions.
|
// Begins definition of frameless function that calls no functions.
|
||||||
.macro .leafprologue
|
.macro .leafprologue
|
||||||
#if !(defined(TINY) && !defined(__PG__))
|
#if !(defined(TINY) && !defined(__PG__))
|
||||||
push %rbp
|
push %rbp
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Ends definition of frameless function that calls no functions.
|
// Ends definition of frameless function that calls no functions.
|
||||||
.macro .leafepilogue
|
.macro .leafepilogue
|
||||||
#if !(defined(TINY) && !defined(__PG__))
|
#if !(defined(TINY) && !defined(__PG__))
|
||||||
pop %rbp
|
pop %rbp
|
||||||
|
@ -39,16 +39,16 @@
|
||||||
ret
|
ret
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Good alignment for functions where alignment actually helps.
|
// Good alignment for functions where alignment actually helps.
|
||||||
/ @note 16-byte
|
// @note 16-byte
|
||||||
.macro .alignfunc
|
.macro .alignfunc
|
||||||
#ifndef __OPTIMIZE_SIZE__
|
#ifndef __OPTIMIZE_SIZE__
|
||||||
.p2align 4
|
.p2align 4
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Good alignment for loops where alignment actually helps.
|
// Good alignment for loops where alignment actually helps.
|
||||||
/ @note 16-byte if <10 padding otherwise 8-byte
|
// @note 16-byte if <10 padding otherwise 8-byte
|
||||||
.macro .alignloop
|
.macro .alignloop
|
||||||
#ifndef __OPTIMIZE_SIZE__
|
#ifndef __OPTIMIZE_SIZE__
|
||||||
.p2align 4,,10
|
.p2align 4,,10
|
||||||
|
@ -56,8 +56,8 @@
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Loads Effective Address
|
// Loads Effective Address
|
||||||
/ Supporting security blankets
|
// Supporting security blankets
|
||||||
.macro plea symbol:req reg64:req reg32:req
|
.macro plea symbol:req reg64:req reg32:req
|
||||||
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
|
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
|
||||||
lea \symbol(%rip),\reg64
|
lea \symbol(%rip),\reg64
|
||||||
|
@ -66,8 +66,8 @@
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Loads Effective Address to Stack
|
// Loads Effective Address to Stack
|
||||||
/ Supporting security blankets
|
// Supporting security blankets
|
||||||
.macro pshaddr symbol:req
|
.macro pshaddr symbol:req
|
||||||
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
|
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
|
||||||
push $IMAGE_BASE_VIRTUAL+RVA(\symbol)(%rip),\reg64
|
push $IMAGE_BASE_VIRTUAL+RVA(\symbol)(%rip),\reg64
|
||||||
|
@ -76,12 +76,12 @@
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ TODO(jart): delete
|
// TODO(jart): delete
|
||||||
/ Loads Effective Address
|
// Loads Effective Address
|
||||||
/ Supporting security blankets
|
// Supporting security blankets
|
||||||
.macro ezlea symbol:req reg:req
|
.macro ezlea symbol:req reg:req
|
||||||
#if __pic__ + __pie__ + __code_model_medium__ + __code_model_large__ + 0 > 1
|
#if __pic__ + __pie__ + __code_model_medium__ + __code_model_large__ + 0 > 1
|
||||||
/ lea \symbol(%rip),%r\reg
|
// lea \symbol(%rip),%r\reg
|
||||||
mov $\symbol,%e\reg
|
mov $\symbol,%e\reg
|
||||||
#else
|
#else
|
||||||
mov $\symbol,%e\reg
|
mov $\symbol,%e\reg
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Creates first stack frame.
|
// Creates first stack frame.
|
||||||
.macro .frame0
|
.macro .frame0
|
||||||
and $-16,%rsp
|
and $-16,%rsp
|
||||||
xor %ebp,%ebp
|
xor %ebp,%ebp
|
||||||
|
@ -106,38 +106,33 @@
|
||||||
.macro .source symbol:req
|
.macro .source symbol:req
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Inserts profiling hook in prologue if cc wants it.
|
// Inserts profiling hook in prologue if cc wants it.
|
||||||
/
|
//
|
||||||
/ Cosmopolitan does this in a slightly different way from normal
|
// Cosmopolitan does this in a slightly different way from normal
|
||||||
/ GNU toolchains. We always use the -mnop-mcount behavior, since
|
// GNU toolchains. We always use the -mnop-mcount behavior, since
|
||||||
/ the runtime is able to morph the binary at runtime. It is good
|
// the runtime is able to morph the binary at runtime. It is good
|
||||||
/ since we can put hooks for profiling and function tracing into
|
// since we can put hooks for profiling and function tracing into
|
||||||
/ most builds, without any impact on performance.
|
// most builds, without any impact on performance.
|
||||||
/
|
//
|
||||||
/ @cost ≥0.3 cycles, 5 bytes
|
// @cost ≥0.3 cycles, 5 bytes
|
||||||
/ @see build/compile
|
// @see build/compile
|
||||||
.macro .profilable
|
.macro .profilable
|
||||||
#ifdef __PG__
|
#ifdef __PG__
|
||||||
1382:
|
1382:
|
||||||
#if defined(__MFENTRY__)
|
#if defined(__MFENTRY__)
|
||||||
call __fentry__
|
call __fentry__
|
||||||
#elif defined(__PIC__) || defined(__PIE__)
|
#elif defined(__PIC__) || defined(__PIE__)
|
||||||
/ nopw 0x00(%rax,%rax,1)
|
// nopw 0x00(%rax,%rax,1)
|
||||||
.byte 0x66,0x0f,0x1f,0x44,0x00,0x00
|
.byte 0x66,0x0f,0x1f,0x44,0x00,0x00
|
||||||
#else
|
#else
|
||||||
/ nopl 0x00(%rax,%rax,1)
|
// nopl 0x00(%rax,%rax,1)
|
||||||
.byte 0x0f,0x1f,0x44,0x00,0x00
|
.byte 0x0f,0x1f,0x44,0x00,0x00
|
||||||
#endif
|
#endif
|
||||||
#if defined(__MRECORD_MCOUNT__) && !defined(__MFENTRY__)
|
|
||||||
.section __mcount_loc,"a",@progbits
|
|
||||||
.quad 1382b
|
|
||||||
.previous
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Pushes RVA on stack of linktime mergeable string literal.
|
// Pushes RVA on stack of linktime mergeable string literal.
|
||||||
/ @see popstr
|
// @see popstr
|
||||||
.macro pushstr text
|
.macro pushstr text
|
||||||
.section .rodata.str1.1,"aSM",@progbits,1
|
.section .rodata.str1.1,"aSM",@progbits,1
|
||||||
.Lstr\@: .asciz "\text"
|
.Lstr\@: .asciz "\text"
|
||||||
|
@ -146,14 +141,14 @@
|
||||||
push $.Lstr\@ - IMAGE_BASE_VIRTUAL
|
push $.Lstr\@ - IMAGE_BASE_VIRTUAL
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Pops off stack string address.
|
// Pops off stack string address.
|
||||||
/ @see pushstr
|
// @see pushstr
|
||||||
.macro popstr dest:req
|
.macro popstr dest:req
|
||||||
addl $IMAGE_BASE_VIRTUAL,(%rsp)
|
addl $IMAGE_BASE_VIRTUAL,(%rsp)
|
||||||
pop \dest
|
pop \dest
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Loads address of linktime mergeable string literal into register.
|
// Loads address of linktime mergeable string literal into register.
|
||||||
.macro getstr text:req reg64:req reg32 regsz64 regsz32 bias=0
|
.macro getstr text:req reg64:req reg32 regsz64 regsz32 bias=0
|
||||||
.section .rodata.str1.1,"aSM",@progbits,1
|
.section .rodata.str1.1,"aSM",@progbits,1
|
||||||
.type .Lstr\@,@object
|
.type .Lstr\@,@object
|
||||||
|
@ -175,8 +170,8 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ TODO(jart): delete
|
// TODO(jart): delete
|
||||||
/ Loads address of linktime mergeable string literal into register.
|
// Loads address of linktime mergeable string literal into register.
|
||||||
.macro loadstr text:req reg:req regsz bias=0
|
.macro loadstr text:req reg:req regsz bias=0
|
||||||
.section .rodata.str1.1,"aSM",@progbits,1
|
.section .rodata.str1.1,"aSM",@progbits,1
|
||||||
.type .Lstr\@,@object
|
.type .Lstr\@,@object
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
|
||||||
#define alignas(x) _Alignas(x)
|
#define alignas(x) _Alignas(x)
|
||||||
#define static_assert(x) _Static_assert(x, #x)
|
|
||||||
|
|
||||||
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
|
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
|
||||||
#define ROUNDDOWN(X, K) ((X) & -(K))
|
#define ROUNDDOWN(X, K) ((X) & -(K))
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
|
||||||
/ Shorthand notation for widely-acknowledged sections.
|
// Shorthand notation for widely-acknowledged sections.
|
||||||
.macro .rodata
|
.macro .rodata
|
||||||
.section .rodata,"a",@progbits
|
.section .rodata,"a",@progbits
|
||||||
.endm
|
.endm
|
||||||
|
@ -62,11 +62,11 @@
|
||||||
.section .text.windows,"ax",@progbits
|
.section .text.windows,"ax",@progbits
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Mergeable numeric constant sections.
|
// Mergeable numeric constant sections.
|
||||||
/
|
//
|
||||||
/ @note linker de-dupes item/values across whole compile
|
// @note linker de-dupes item/values across whole compile
|
||||||
/ @note therefore item/values are reordered w.r.t. link order
|
// @note therefore item/values are reordered w.r.t. link order
|
||||||
/ @note therefore no section relative addressing
|
// @note therefore no section relative addressing
|
||||||
.macro .rodata.cst4
|
.macro .rodata.cst4
|
||||||
.section .rodata.cst4,"aM",@progbits,4
|
.section .rodata.cst4,"aM",@progbits,4
|
||||||
.align 4
|
.align 4
|
||||||
|
@ -96,33 +96,33 @@
|
||||||
.align 4
|
.align 4
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Mergeable NUL-terminated UTF-8 string constant section.
|
// Mergeable NUL-terminated UTF-8 string constant section.
|
||||||
/
|
//
|
||||||
/ @note linker de-dupes C strings here across whole compile
|
// @note linker de-dupes C strings here across whole compile
|
||||||
/ @note therefore item/values are reordered w.r.t. link order
|
// @note therefore item/values are reordered w.r.t. link order
|
||||||
/ @note therefore no section relative addressing
|
// @note therefore no section relative addressing
|
||||||
.macro .rodata.str1.1
|
.macro .rodata.str1.1
|
||||||
.section .rodata.str1.1,"aSM",@progbits,1
|
.section .rodata.str1.1,"aSM",@progbits,1
|
||||||
.align 1
|
.align 1
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Locates unreferenced code invulnerable to --gc-sections.
|
// Locates unreferenced code invulnerable to --gc-sections.
|
||||||
.macro .keep.text
|
.macro .keep.text
|
||||||
.section .keep.text,"ax",@progbits
|
.section .keep.text,"ax",@progbits
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Flags code as only allowed for testing purposes.
|
// Flags code as only allowed for testing purposes.
|
||||||
.macro .testonly
|
.macro .testonly
|
||||||
.section .test,"ax",@progbits
|
.section .test,"ax",@progbits
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Makes code runnable while code morphing.
|
// Makes code runnable while code morphing.
|
||||||
.macro .privileged
|
.macro .privileged
|
||||||
.section .privileged,"ax",@progbits
|
.section .privileged,"ax",@progbits
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Post-Initialization Read-Only (PIRO) BSS section.
|
// Post-Initialization Read-Only (PIRO) BSS section.
|
||||||
/ @param ss is an optional string, for control image locality
|
// @param ss is an optional string, for control image locality
|
||||||
.macro .piro ss
|
.macro .piro ss
|
||||||
.ifnb \ss
|
.ifnb \ss
|
||||||
.section .piro.sort.bss.\ss,"aw",@nobits
|
.section .piro.sort.bss.\ss,"aw",@nobits
|
||||||
|
@ -131,9 +131,9 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Helpers for Cosmopolitan _init() amalgamation magic.
|
// Helpers for Cosmopolitan _init() amalgamation magic.
|
||||||
/ @param name should be consistent across macros for a module
|
// @param name should be consistent across macros for a module
|
||||||
/ @see libc/runtime/_init.S
|
// @see libc/runtime/_init.S
|
||||||
.macro .initro number:req name:req
|
.macro .initro number:req name:req
|
||||||
.section .initro.\number\().\name,"a",@progbits
|
.section .initro.\number\().\name,"a",@progbits
|
||||||
.align 8
|
.align 8
|
||||||
|
@ -151,16 +151,16 @@
|
||||||
.previous
|
.previous
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Declares alternative implementation of function.
|
// Declares alternative implementation of function.
|
||||||
/ @param implement e.g. tinymath_pow
|
// @param implement e.g. tinymath_pow
|
||||||
/ @param canonical e.g. pow
|
// @param canonical e.g. pow
|
||||||
.macro .alias implement:req canonical:req
|
.macro .alias implement:req canonical:req
|
||||||
.equ \canonical,\implement
|
.equ \canonical,\implement
|
||||||
.weak \canonical
|
.weak \canonical
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Ends function definition.
|
// Ends function definition.
|
||||||
/ @cost saves 1-3 lines of code
|
// @cost saves 1-3 lines of code
|
||||||
.macro .endfn name:req bnd vis
|
.macro .endfn name:req bnd vis
|
||||||
.size \name,.-\name
|
.size \name,.-\name
|
||||||
.type \name,@function
|
.type \name,@function
|
||||||
|
@ -172,8 +172,8 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Ends variable definition.
|
// Ends variable definition.
|
||||||
/ @cost saves 1-3 lines of code
|
// @cost saves 1-3 lines of code
|
||||||
.macro .endobj name:req bnd vis
|
.macro .endobj name:req bnd vis
|
||||||
.size \name,.-\name
|
.size \name,.-\name
|
||||||
.type \name,@object
|
.type \name,@object
|
||||||
|
@ -185,35 +185,35 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ LOOP Instruction Replacement.
|
// LOOP Instruction Replacement.
|
||||||
/ With its mop-Fusion Mexican equivalent.
|
// With its mop-Fusion Mexican equivalent.
|
||||||
/ Thus avoiding 3x legacy pipeline slowdown.
|
// Thus avoiding 3x legacy pipeline slowdown.
|
||||||
.macro .loop label:req
|
.macro .loop label:req
|
||||||
.byte 0x83,0xe9,0x01 # sub $1,%ecx
|
.byte 0x83,0xe9,0x01 # sub $1,%ecx
|
||||||
jnz \label
|
jnz \label
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Pushes CONSTEXPR ∈ [-128,127].
|
// Pushes CONSTEXPR ∈ [-128,127].
|
||||||
/ @note assembler is wrong for non-literal constexprs
|
// @note assembler is wrong for non-literal constexprs
|
||||||
.macro pushb x:req
|
.macro pushb x:req
|
||||||
.byte 0x6a,\x
|
.byte 0x6a,\x
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Sign-extends CONSTEXPR ∈ [-128,127] to REGISTER.
|
// Sign-extends CONSTEXPR ∈ [-128,127] to REGISTER.
|
||||||
/ @cost ≥1 cycles, -2 bytes
|
// @cost ≥1 cycles, -2 bytes
|
||||||
.macro pushpop constexpr:req register:req
|
.macro pushpop constexpr:req register:req
|
||||||
pushb \constexpr
|
pushb \constexpr
|
||||||
pop \register
|
pop \register
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Moves REGISTER to REGISTER.
|
// Moves REGISTER to REGISTER.
|
||||||
/ @cost ≥1 cycles, -1 REX byte
|
// @cost ≥1 cycles, -1 REX byte
|
||||||
.macro movpp src:req dest:req
|
.macro movpp src:req dest:req
|
||||||
push \src
|
push \src
|
||||||
pop \dest
|
pop \dest
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Declares optional function.
|
// Declares optional function.
|
||||||
.macro .optfn fn:req
|
.macro .optfn fn:req
|
||||||
.globl \fn
|
.globl \fn
|
||||||
.weak \fn
|
.weak \fn
|
||||||
|
@ -221,8 +221,8 @@
|
||||||
.type \fn,@function
|
.type \fn,@function
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Embeds fixed-width zero-filled string table.
|
// Embeds fixed-width zero-filled string table.
|
||||||
/ @note zero-padded ≠ nul-terminated
|
// @note zero-padded ≠ nul-terminated
|
||||||
.macro .fxstr width head rest:vararg
|
.macro .fxstr width head rest:vararg
|
||||||
.ifnb \head
|
.ifnb \head
|
||||||
0: .ascii "\head"
|
0: .ascii "\head"
|
||||||
|
@ -231,15 +231,15 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Embeds Fixed-Width Zero-Padded String.
|
// Embeds Fixed-Width Zero-Padded String.
|
||||||
/ @note .fxstr is better
|
// @note .fxstr is better
|
||||||
.macro .ascin str:req fieldsize:req
|
.macro .ascin str:req fieldsize:req
|
||||||
1347: .ascii "\str"
|
1347: .ascii "\str"
|
||||||
.org 1347b+\fieldsize,0x00
|
.org 1347b+\fieldsize,0x00
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Marks symbols as object en-masse.
|
// Marks symbols as object en-masse.
|
||||||
/ @note zero-padded ≠ nul-terminated
|
// @note zero-padded ≠ nul-terminated
|
||||||
.macro .object symbol rest:vararg
|
.macro .object symbol rest:vararg
|
||||||
.ifnb \symbol
|
.ifnb \symbol
|
||||||
.type \symbol,@object
|
.type \symbol,@object
|
||||||
|
@ -247,18 +247,14 @@
|
||||||
.endif
|
.endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Pads function prologue unconditionally for runtime hooking.
|
// Pads function prologue unconditionally for runtime hooking.
|
||||||
/ @cost ≥0.3 cycles, 5 bytes
|
// @cost ≥0.3 cycles, 5 bytes
|
||||||
/ @see .profilable
|
// @see .profilable
|
||||||
.macro .hookable
|
.macro .hookable
|
||||||
/ nopl 0x00(%rax,%rax,1)
|
.byte 0x0f,0x1f,0x44,0x00,0x00
|
||||||
83457: .byte 0x0f,0x1f,0x44,0x00,0x00
|
|
||||||
.section __mcount_loc,"a",@progbits
|
|
||||||
.quad 83457b
|
|
||||||
.previous
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Puts initialized data in uninitialized data section.
|
// Puts initialized data in uninitialized data section.
|
||||||
.macro .bsdata name:req expr:req bnd vis
|
.macro .bsdata name:req expr:req bnd vis
|
||||||
.section .initbss.300._init_\name,"aw",@nobits
|
.section .initbss.300._init_\name,"aw",@nobits
|
||||||
\name: .quad 0
|
\name: .quad 0
|
||||||
|
@ -274,9 +270,9 @@ _init_\name:
|
||||||
.previous
|
.previous
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ ICE Breakpoint.
|
// ICE Breakpoint.
|
||||||
/ Modern gas forgot this but objdump knows
|
// Modern gas forgot this but objdump knows
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro icebp
|
.macro icebp
|
||||||
.byte 0xF1
|
.byte 0xF1
|
||||||
.endm
|
.endm
|
||||||
|
@ -284,8 +280,8 @@ _init_\name:
|
||||||
icebp
|
icebp
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Sets breakpoint for software debugger.
|
// Sets breakpoint for software debugger.
|
||||||
/ @mode long,legacy,real
|
// @mode long,legacy,real
|
||||||
.macro .softicebp
|
.macro .softicebp
|
||||||
.byte 0x53 # push bx
|
.byte 0x53 # push bx
|
||||||
.byte 0x87,0xdb # xchg bx,bx (bochs breakpoint)
|
.byte 0x87,0xdb # xchg bx,bx (bochs breakpoint)
|
||||||
|
@ -294,38 +290,38 @@ _init_\name:
|
||||||
int3 # gdb breakpoint
|
int3 # gdb breakpoint
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Assembles Intel Official 4-Byte NOP.
|
// Assembles Intel Official 4-Byte NOP.
|
||||||
.macro fatnop4
|
.macro fatnop4
|
||||||
.byte 0x0f,0x1f,0x40,0x00
|
.byte 0x0f,0x1f,0x40,0x00
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Pulls unrelated module into linkage.
|
// Pulls unrelated module into linkage.
|
||||||
/
|
//
|
||||||
/ In order for this technique to work with --gc-sections, another
|
// In order for this technique to work with --gc-sections, another
|
||||||
/ module somewhere might want to weakly reference whats yoinked.
|
// module somewhere might want to weakly reference whats yoinked.
|
||||||
.macro yoink symbol:req
|
.macro yoink symbol:req
|
||||||
.section .yoink
|
.section .yoink
|
||||||
nop "\symbol"
|
nopl "\symbol"(%rip)
|
||||||
.previous
|
.previous
|
||||||
.endm
|
.endm
|
||||||
.macro .yoink symbol:req
|
.macro .yoink symbol:req
|
||||||
.section .yoink
|
.section .yoink
|
||||||
nop "\symbol"
|
nopl "\symbol"(%rip)
|
||||||
.previous
|
.previous
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Calls Windows function.
|
// Calls Windows function.
|
||||||
/
|
//
|
||||||
/ @param cx,dx,r8,r9,stack
|
// @param cx,dx,r8,r9,stack
|
||||||
/ @return ax
|
// @return ax
|
||||||
/ @clob ax,cx,dx,r8-r11
|
// @clob ax,cx,dx,r8-r11
|
||||||
.macro ntcall symbol:req
|
.macro ntcall symbol:req
|
||||||
sub $32,%rsp
|
sub $32,%rsp
|
||||||
call *\symbol(%rip)
|
call *\symbol(%rip)
|
||||||
add $32,%rsp
|
add $32,%rsp
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/ Custom emulator instruction for bottom stack frame.
|
// Custom emulator instruction for bottom stack frame.
|
||||||
.macro bofram endfunc:req
|
.macro bofram endfunc:req
|
||||||
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
|
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
#include "libc/notice.inc"
|
#include "libc/notice.inc"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Allocates n * itemsize bytes, initialized to zero.
|
// Allocates n * itemsize bytes, initialized to zero.
|
||||||
/
|
//
|
||||||
/ @param rdi is number of items (n)
|
// @param rdi is number of items (n)
|
||||||
/ @param rsi is size of each item (itemsize)
|
// @param rsi is size of each item (itemsize)
|
||||||
/ @return rax is memory address, or NULL w/ errno
|
// @return rax is memory address, or NULL w/ errno
|
||||||
/ @note overreliance on memalign is a sure way to fragment space
|
// @note overreliance on memalign is a sure way to fragment space
|
||||||
/ @see dlcalloc()
|
// @see dlcalloc()
|
||||||
calloc: jmp *hook_calloc(%rip)
|
calloc: jmp *hook_calloc(%rip)
|
||||||
.endfn calloc,globl
|
.endfn calloc,globl
|
||||||
|
|
|
@ -19,67 +19,67 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Frees memory the C++ way.
|
// Frees memory the C++ way.
|
||||||
/
|
//
|
||||||
/ \param %rdi is pointer, or NULL for no-op
|
// \param %rdi is pointer, or NULL for no-op
|
||||||
/ \param %rsi is ignored
|
// \param %rsi is ignored
|
||||||
/ \param %rdx is ignored
|
// \param %rdx is ignored
|
||||||
_ZdlPvSt11align_val_tRKSt9nothrow_t:
|
_ZdlPvSt11align_val_tRKSt9nothrow_t:
|
||||||
/ operator delete(void*, std::align_val_t, std::nothrow_t const&)
|
// operator delete(void*, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
|
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZdaPvSt11align_val_tRKSt9nothrow_t:
|
_ZdaPvSt11align_val_tRKSt9nothrow_t:
|
||||||
/ operator delete[](void*, std::align_val_t, std::nothrow_t const&)
|
// operator delete[](void*, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
|
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZdlPvRKSt9nothrow_t:
|
_ZdlPvRKSt9nothrow_t:
|
||||||
/ operator delete(void*, std::nothrow_t const&)
|
// operator delete(void*, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdlPvRKSt9nothrow_t,weak
|
.endfn _ZdlPvRKSt9nothrow_t,weak
|
||||||
_ZdaPvRKSt9nothrow_t:
|
_ZdaPvRKSt9nothrow_t:
|
||||||
/ operator delete[](void*, std::nothrow_t const&)
|
// operator delete[](void*, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPvRKSt9nothrow_t,weak
|
.endfn _ZdaPvRKSt9nothrow_t,weak
|
||||||
_ZdlPvmSt11align_val_t:
|
_ZdlPvmSt11align_val_t:
|
||||||
/ operator delete(void*, unsigned long, std::align_val_t)
|
// operator delete(void*, unsigned long, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdlPvmSt11align_val_t,weak
|
.endfn _ZdlPvmSt11align_val_t,weak
|
||||||
_ZdaPvmSt11align_val_t:
|
_ZdaPvmSt11align_val_t:
|
||||||
/ operator delete[](void*, unsigned long, std::align_val_t)
|
// operator delete[](void*, unsigned long, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPvmSt11align_val_t,weak
|
.endfn _ZdaPvmSt11align_val_t,weak
|
||||||
_ZdlPvSt11align_val_t:
|
_ZdlPvSt11align_val_t:
|
||||||
/ operator delete(void*, std::align_val_t)
|
// operator delete(void*, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdlPvSt11align_val_t,weak
|
.endfn _ZdlPvSt11align_val_t,weak
|
||||||
_ZdaPvSt11align_val_t:
|
_ZdaPvSt11align_val_t:
|
||||||
/ operator delete[](void*, std::align_val_t)
|
// operator delete[](void*, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPvSt11align_val_t,weak
|
.endfn _ZdaPvSt11align_val_t,weak
|
||||||
_ZdaPvm:
|
_ZdaPvm:
|
||||||
/ operator delete[](void*, unsigned long):
|
// operator delete[](void*, unsigned long):
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPvm,weak
|
.endfn _ZdaPvm,weak
|
||||||
_ZdlPvm:
|
_ZdlPvm:
|
||||||
/ operator delete(void*, unsigned long)
|
// operator delete(void*, unsigned long)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdlPvm,weak
|
.endfn _ZdlPvm,weak
|
||||||
_ZdaPv:
|
_ZdaPv:
|
||||||
/ operator delete[](void*)
|
// operator delete[](void*)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPv,weak
|
.endfn _ZdaPv,weak
|
||||||
_ZdlPv:
|
_ZdlPv:
|
||||||
/ operator delete(void*)
|
// operator delete(void*)
|
||||||
jmp *hook_free(%rip)
|
jmp *hook_free(%rip)
|
||||||
.endfn _ZdlPv,weak
|
.endfn _ZdlPv,weak
|
||||||
|
|
|
@ -19,28 +19,28 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Allocates memory the C++ way.
|
// Allocates memory the C++ way.
|
||||||
/
|
//
|
||||||
/ \param %rdi is bytes to allocate
|
// \param %rdi is bytes to allocate
|
||||||
/ \param %rsi is ignored
|
// \param %rsi is ignored
|
||||||
/ \return new memory or NULL on OOM
|
// \return new memory or NULL on OOM
|
||||||
_ZnamRKSt9nothrow_t:
|
_ZnamRKSt9nothrow_t:
|
||||||
/ operator new[](unsigned long, std::nothrow_t const&)
|
// operator new[](unsigned long, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZnamRKSt9nothrow_t,weak
|
.endfn _ZnamRKSt9nothrow_t,weak
|
||||||
_ZnwmRKSt9nothrow_t:
|
_ZnwmRKSt9nothrow_t:
|
||||||
/ operator new(unsigned long, std::nothrow_t const&)
|
// operator new(unsigned long, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZnwmRKSt9nothrow_t,weak
|
.endfn _ZnwmRKSt9nothrow_t,weak
|
||||||
_Znam:
|
_Znam:
|
||||||
/ operator new[](unsigned long)
|
// operator new[](unsigned long)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _Znam,weak
|
.endfn _Znam,weak
|
||||||
_Znwm:
|
_Znwm:
|
||||||
/ operator new(unsigned long)
|
// operator new(unsigned long)
|
||||||
test %rdi,%rdi
|
test %rdi,%rdi
|
||||||
jne 1f
|
jne 1f
|
||||||
mov $1,%edi
|
mov $1,%edi
|
||||||
|
|
|
@ -19,29 +19,29 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Allocates aligned memory the C++ way.
|
// Allocates aligned memory the C++ way.
|
||||||
/
|
//
|
||||||
/ \param %rdi is bytes to allocate
|
// \param %rdi is bytes to allocate
|
||||||
/ \param %rsi is byte alignment
|
// \param %rsi is byte alignment
|
||||||
/ \param %rdx is ignored
|
// \param %rdx is ignored
|
||||||
/ \return new memory or NULL on OOM
|
// \return new memory or NULL on OOM
|
||||||
_ZnamSt11align_val_tRKSt9nothrow_t:
|
_ZnamSt11align_val_tRKSt9nothrow_t:
|
||||||
/ operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
|
// operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
|
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZnwmSt11align_val_tRKSt9nothrow_t:
|
_ZnwmSt11align_val_tRKSt9nothrow_t:
|
||||||
/ operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
|
// operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
|
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZnwmSt11align_val_t:
|
_ZnwmSt11align_val_t:
|
||||||
/ operator new(unsigned long, std::align_val_t)
|
// operator new(unsigned long, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
/ 𝑠𝑙𝑖𝑑𝑒
|
// 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZnwmSt11align_val_t,weak
|
.endfn _ZnwmSt11align_val_t,weak
|
||||||
_ZnamSt11align_val_t:
|
_ZnamSt11align_val_t:
|
||||||
/ operator new[](unsigned long, std::align_val_t)
|
// operator new[](unsigned long, std::align_val_t)
|
||||||
test %rdi,%rdi
|
test %rdi,%rdi
|
||||||
jnz 1f
|
jnz 1f
|
||||||
mov $1,%eax
|
mov $1,%eax
|
||||||
|
|
|
@ -16,9 +16,8 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/alg/arraylist.internal.h"
|
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/likely.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/nexgen32e/gc.internal.h"
|
#include "libc/nexgen32e/gc.internal.h"
|
||||||
|
@ -41,22 +40,26 @@ forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
|
||||||
* @return arg
|
* @return arg
|
||||||
*/
|
*/
|
||||||
void __defer(struct StackFrame *frame, void *fn, void *arg) {
|
void __defer(struct StackFrame *frame, void *fn, void *arg) {
|
||||||
struct StackFrame *frame2;
|
size_t n2;
|
||||||
/*
|
struct Garbage *p2;
|
||||||
* To avoid an API requiring dlmalloc dependency, say:
|
struct StackFrame *f2;
|
||||||
* defer(free_s, &ptr_not_owned_by_current_frame)
|
|
||||||
* Rather than:
|
|
||||||
* defer(weak(free), ptr)
|
|
||||||
*/
|
|
||||||
if (!arg) return;
|
if (!arg) return;
|
||||||
frame2 = __builtin_frame_address(0);
|
f2 = __builtin_frame_address(0);
|
||||||
assert(frame2->next == frame);
|
assert(__garbage.n);
|
||||||
assert(PointerNotOwnedByParentStackFrame(frame2, frame, arg));
|
assert(f2->next == frame);
|
||||||
if (append(&__garbage,
|
assert(PointerNotOwnedByParentStackFrame(f2, frame, arg));
|
||||||
(&(const struct Garbage){frame->next, (intptr_t)fn, (intptr_t)arg,
|
if (UNLIKELY(__garbage.i == __garbage.n)) {
|
||||||
frame->addr})) != -1) {
|
n2 = __garbage.n + (__garbage.n >> 1);
|
||||||
atomic_store(&frame->addr, (intptr_t)&__gc);
|
p2 = malloc(n2 * sizeof(*__garbage.p));
|
||||||
} else {
|
memcpy(p2, __garbage.p, __garbage.n * sizeof(*__garbage.p));
|
||||||
abort();
|
if (__garbage.p != __garbage.initmem) free(__garbage.p);
|
||||||
|
__garbage.p = p2;
|
||||||
|
__garbage.n = n2;
|
||||||
}
|
}
|
||||||
|
__garbage.p[__garbage.i].frame = frame->next;
|
||||||
|
__garbage.p[__garbage.i].fn = (intptr_t)fn;
|
||||||
|
__garbage.p[__garbage.i].arg = (intptr_t)arg;
|
||||||
|
__garbage.p[__garbage.i].ret = frame->addr;
|
||||||
|
__garbage.i++;
|
||||||
|
frame->addr = (intptr_t)__gc;
|
||||||
}
|
}
|
|
@ -19,15 +19,15 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Free memory returned by malloc() & co.
|
// Free memory returned by malloc() & co.
|
||||||
/
|
//
|
||||||
/ Releases the chunk of memory pointed to by p, that had been
|
// Releases the chunk of memory pointed to by p, that had been
|
||||||
/ previously allocated using malloc or a related routine such as
|
// previously allocated using malloc or a related routine such as
|
||||||
/ realloc. It has no effect if p is null. If p was not malloced or
|
// realloc. It has no effect if p is null. If p was not malloced or
|
||||||
/ already freed, free(p) will by default cuase the current program to
|
// already freed, free(p) will by default cuase the current program to
|
||||||
/ abort.
|
// abort.
|
||||||
/
|
//
|
||||||
/ @param rdi is allocation address, which may be NULL
|
// @param rdi is allocation address, which may be NULL
|
||||||
/ @see dlfree()
|
// @see dlfree()
|
||||||
free: jmp *hook_free(%rip)
|
free: jmp *hook_free(%rip)
|
||||||
.endfn free,globl
|
.endfn free,globl
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue