Get codebase completely working with LLVM

You can now build Cosmopolitan with Clang:

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

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

View file

@ -117,8 +117,6 @@ include third_party/gdtoa/gdtoa.mk # │ You can finally call malloc()
include libc/time/time.mk # │
include libc/alg/alg.mk # │
include libc/stdio/stdio.mk # │
include third_party/f2c/f2c.mk # │
include third_party/blas/blas.mk # │
include net/net.mk # │
include libc/log/log.mk # │
include dsp/core/core.mk # │
@ -203,7 +201,7 @@ CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
bins: $(BINS)
check: $(CHECKS)
test: $(TESTS)
test: $(TESTS) all
depend: o/$(MODE)/depend
tags: TAGS HTAGS

View file

@ -4,10 +4,10 @@
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
a build-once run-anywhere language, like Java, except it doesn't need an
interpreter or virtual machine. Instead, it reconfigures stock GCC to
output a POSIX-approved polyglot format that runs natively on Linux +
Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best possible
performance and the tiniest footprint imaginable.
interpreter or virtual machine. Instead, it reconfigures stock GCC and
Clang to output a POSIX-approved polyglot format that runs natively on
Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best
possible performance and the tiniest footprint imaginable.
## Background
@ -18,24 +18,33 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have
## 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
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
cd cosmopolitan-0.1.2
make -j16
o//examples/hello.com
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
```

880
ape/ape.S

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@
entails two steps: (1) create a .com.dbg binary w/ Linux toolchain and
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.
@ -182,21 +182,6 @@
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 {
Head PT_LOAD FLAGS(5);
Rom PT_LOAD FLAGS(5);
@ -221,34 +206,34 @@ SECTIONS {
/* Executable & Linkable Format */
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
KEEP(*(.elf.phdrs))
HIDDEN(.Lape.phdrs.end = .);
HIDDEN(ape_phdrs_end = .);
. += 1;
/* OpenBSD */
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 1);
HIDDEN(.Lape.note = .);
HIDDEN(ape_note = .);
KEEP(*(.note.openbsd.ident))
KEEP(*(.note.netbsd.ident))
HIDDEN(.Lape.note.end = .);
HIDDEN(ape_note_end = .);
. += 1;
/* Portable Executable */
KEEP(*(.pe.header))
HIDDEN(.Lape.pe.sections = .);
HIDDEN(ape_pe_sections = .);
KEEP(*(.pe.sections))
HIDDEN(.Lape.pe.sections_end = .);
HIDDEN(ape_pe_sections_end = .);
. += 1;
/* Mach-O */
KEEP(*(.macho))
. = ALIGN(__SIZEOF_POINTER__);
HIDDEN(.Lape.macho.end = .);
HIDDEN(ape_macho_end = .);
. += 1;
KEEP(*(.ape.pad.head))
. = ALIGN(SupportsWindows() ? PAGESIZE : 16);
HIDDEN(_ehead = .);
} AT>SmallCode :Head
} :Head
/*BEGIN: nt addressability guarantee */
@ -266,7 +251,7 @@ SECTIONS {
*(.start)
KEEP(*(.initprologue))
KEEP(*(SORT_BY_NAME(.init.*)))
KEEP(*(SORT_NONE(.init)))
KEEP(*(.init))
KEEP(*(.initepilogue))
KEEP(*(.pltprologue))
*(.plt)
@ -290,19 +275,13 @@ SECTIONS {
*(.text .stub .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));
. = ALIGN(.Lape.piro.align);
HIDDEN(__test_start = .);
*(.test.unlikely)
*(.test .test.*)
/* Privileged code invulnerable to magic */
KEEP(*(.ape.pad.privileged));
. = ALIGN(.Lape.piro.align);
HIDDEN(__privileged_start = .);
HIDDEN(__test_end = .);
. += 1;
@ -312,23 +291,10 @@ SECTIONS {
/*BEGIN: Read Only Data */
KEEP(*(.ape.pad.rodata));
. = ALIGN(.Lape.piro.align);
. += 1;
/* Nonspecific Read-Only Data */
*(.rodata .rodata.*)
. += 1;
/* Undefined Behavior Sanitizer Types */
HIDDEN(__ubsan_types_start = .);
*(.ubsan.types)
HIDDEN(__ubsan_types_end = .);
. += 1;
/* Undefined Behavior Sanitizer Data */
HIDDEN(__ubsan_data_start = .);
*(.ubsan.data)
HIDDEN(__ubsan_data_end = .);
/* Unit Test & Fixture Registry */
@ -340,7 +306,7 @@ SECTIONS {
KEEP(*(.comment))
KEEP(*(.commentepilogue))
#endif
/* Windows DLL Import Directory */
KEEP(*(.idata.ro));
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
@ -350,16 +316,16 @@ SECTIONS {
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP(*(SORT_NONE(.ctors)))
KEEP(*(SORT_NONE(.init_array)))
KEEP(*(SORT_NONE(.preinit_array)))
KEEP(*(.ctors))
KEEP(*(.init_array))
KEEP(*(.preinit_array))
PROVIDE_HIDDEN(__init_array_end = .);
. = ALIGN(__SIZEOF_POINTER__);
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(SORT_NONE(.dtors)))
KEEP(*(.dtors))
PROVIDE_HIDDEN(__fini_array_end = .);
/* Encoded Data Structures w/ Linear Initialization Order */
@ -369,13 +335,12 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
KEEP(*(.ape.pad.text))
HIDDEN(.Lape.data.align = ABSOLUTE(PAGESIZE));
. = ALIGN(.Lape.data.align);
. = ALIGN(PAGESIZE);
HIDDEN(_etext = .);
PROVIDE_HIDDEN(etext = .);
/*END: Read Only Data (only needed for initialization) */
/*END: Read Only Data */
} AT>SmallCode :Rom
} :Rom
.data . : {
/*BEGIN: Read/Write Data */
@ -393,24 +358,21 @@ SECTIONS {
KEEP(*(.gotpltepilogue))
/*BEGIN: Post-Initialization Read-Only */
. = ALIGN(.Lape.piro.align);
HIDDEN(__piro_start = .);
. = ALIGN(__SIZEOF_POINTER__);
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
PROVIDE_HIDDEN(__relo_end = .);
. = ALIGN(__SIZEOF_POINTER__);
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
KEEP(*(.piro.pad.data))
. = ALIGN(.Lape.data.align);
. = ALIGN(PAGESIZE);
HIDDEN(_edata = .);
PROVIDE_HIDDEN(edata = .);
} AT>SmallCode :Ram
} :Ram
.bss . : {
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
*(.piro.bss)
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
. += 1;
. = ALIGN(.Lape.piro.align);
HIDDEN(__piro_end = .);
/*END: Post-Initialization Read-Only */
@ -429,13 +391,16 @@ SECTIONS {
. = ALIGN(0x10000); /* for brk()/sbrk() allocation */
HIDDEN(_end = .);
PROVIDE_HIDDEN(end = .);
} AT>SmallCode :Ram
} :Ram
/*END: nt addressability guarantee */
/*END: bsd addressability guarantee */
/*END: linux addressability guarantee */
/*END: xnu addressability guarantee */
.shstrtab : { *(.shstrtab) }
.strtab : { *(.strtab) }
.symtab : { *(.symtab) }
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
@ -468,80 +433,81 @@ SECTIONS {
.GCC.command.line 0 : { *(.GCC.command.line) }
/DISCARD/ : {
*(__mcount_loc)
*(.discard)
*(.yoink)
*(.*)
}
}
PFSTUB8(.Lape.elf.entry, _start);
PFSTUB8(.Lape.elf.phoff, RVA(ape.phdrs));
PFSTUB8(.Lape.elf.shoff, 0);
PFSTUB4(.Lape.elf.phnum, (.Lape.phdrs.end - ape.phdrs) / 56);
PFSTUB4(.Lape.elf.shnum, 0);
PFSTUB4(.Lape.elf.shstrndx, 0);
PFSTUB8(ape_elf_entry, _start);
PFSTUB8(ape_elf_phoff, RVA(ape_phdrs));
PFSTUB8(ape_elf_shoff, 0);
PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
PFSTUB4(ape_elf_shnum, 0);
PFSTUB4(ape_elf_shstrndx, 0);
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
ROUNDDOWN(__privileged_start, PAGESIZE)));
HIDDEN(.Lape.rom.offset = 0);
HIDDEN(.Lape.rom.vaddr = ADDR(.head));
HIDDEN(.Lape.rom.paddr = LOADADDR(.head));
HIDDEN(.Lape.rom.filesz = LOADADDR(.data) - .Lape.rom.paddr);
HIDDEN(.Lape.rom.memsz = ADDR(.data) - ADDR(.head));
HIDDEN(.Lape.rom.align = .Lape.data.align);
HIDDEN(.Lape.rom.rva = RVA(.Lape.rom.vaddr));
HIDDEN(ape_rom_offset = 0);
HIDDEN(ape_rom_vaddr = ADDR(.head));
HIDDEN(ape_rom_paddr = LOADADDR(.head));
HIDDEN(ape_rom_filesz = LOADADDR(.data) - ape_rom_paddr);
HIDDEN(ape_rom_memsz = ADDR(.data) - ADDR(.head));
HIDDEN(ape_rom_align = PAGESIZE);
HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
HIDDEN(.Lape.ram.offset = .Lape.rom.offset + .Lape.rom.filesz);
HIDDEN(.Lape.ram.vaddr = ADDR(.data));
HIDDEN(.Lape.ram.paddr = LOADADDR(.data));
HIDDEN(.Lape.ram.filesz = LOADADDR(.bss) - LOADADDR(.data));
HIDDEN(.Lape.ram.memsz = ADDR(.bss) + SIZEOF(.bss) - .Lape.ram.vaddr);
HIDDEN(.Lape.ram.align = .Lape.data.align);
HIDDEN(.Lape.ram.rva = RVA(.Lape.ram.vaddr));
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
HIDDEN(ape_ram_vaddr = ADDR(.data));
HIDDEN(ape_ram_paddr = LOADADDR(.data));
HIDDEN(ape_ram_filesz = LOADADDR(.bss) - LOADADDR(.data));
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
HIDDEN(ape_ram_align = PAGESIZE);
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
HIDDEN(.Lape.note.offset = .Lape.rom.offset + (.Lape.note - .Lape.rom.vaddr));
HIDDEN(.Lape.note.vaddr = .Lape.note);
HIDDEN(.Lape.note.paddr = .Lape.rom.paddr + .Lape.note.offset);
HIDDEN(.Lape.note.filesz = .Lape.note.end - .Lape.note);
HIDDEN(.Lape.note.memsz = .Lape.note.filesz);
HIDDEN(.Lape.note.align = __SIZEOF_POINTER__);
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
HIDDEN(ape_note_vaddr = ape_note);
HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset);
HIDDEN(ape_note_filesz = ape_note_end - ape_note);
HIDDEN(ape_note_memsz = ape_note_filesz);
HIDDEN(ape_note_align = __SIZEOF_POINTER__);
HIDDEN(.Lape.text.offset = .Lape.rom.offset + LOADADDR(.text) - .Lape.rom.paddr);
HIDDEN(.Lape.text.paddr = LOADADDR(.text));
HIDDEN(.Lape.text.vaddr = ADDR(.text));
HIDDEN(.Lape.text.filesz = SIZEOF(.text));
HIDDEN(.Lape.text.memsz = SIZEOF(.text));
HIDDEN(.Lape.text.align = 4096);
HIDDEN(.Lape.text.rva = RVA(.Lape.text.vaddr));
HIDDEN(ape_text_offset = ape_rom_offset + LOADADDR(.text) - ape_rom_paddr);
HIDDEN(ape_text_paddr = LOADADDR(.text));
HIDDEN(ape_text_vaddr = ADDR(.text));
HIDDEN(ape_text_filesz = SIZEOF(.text));
HIDDEN(ape_text_memsz = SIZEOF(.text));
HIDDEN(ape_text_align = PAGESIZE);
HIDDEN(ape_text_rva = RVA(ape_text_vaddr));
HIDDEN(.Lape.data.offset = .Lape.ram.offset + LOADADDR(.data) - .Lape.ram.paddr);
HIDDEN(.Lape.data.paddr = LOADADDR(.data));
HIDDEN(.Lape.data.vaddr = ADDR(.data));
HIDDEN(.Lape.data.filesz = SIZEOF(.data));
HIDDEN(.Lape.data.memsz = SIZEOF(.data));
HIDDEN(.Lape.data.align = .Lape.data.align);
HIDDEN(.Lape.data.rva = RVA(.Lape.data.vaddr));
HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr);
HIDDEN(ape_data_paddr = LOADADDR(.data));
HIDDEN(ape_data_vaddr = ADDR(.data));
HIDDEN(ape_data_filesz = SIZEOF(.data));
HIDDEN(ape_data_memsz = SIZEOF(.data));
HIDDEN(ape_data_align = PAGESIZE);
HIDDEN(ape_data_rva = RVA(ape_data_vaddr));
HIDDEN(.Lape.bss.offset = .Lape.ram.offset + LOADADDR(.bss) - .Lape.ram.paddr);
HIDDEN(.Lape.bss.paddr = LOADADDR(.bss));
HIDDEN(.Lape.bss.vaddr = ADDR(.bss));
HIDDEN(.Lape.bss.filesz = 0);
HIDDEN(.Lape.bss.memsz = SIZEOF(.bss));
HIDDEN(.Lape.bss.align = .Lape.data.align);
HIDDEN(ape_bss_offset = ape_ram_offset + LOADADDR(.bss) - ape_ram_paddr);
HIDDEN(ape_bss_paddr = LOADADDR(.bss));
HIDDEN(ape_bss_vaddr = ADDR(.bss));
HIDDEN(ape_bss_filesz = 0);
HIDDEN(ape_bss_memsz = SIZEOF(.bss));
HIDDEN(ape_bss_align = PAGESIZE);
#if SupportsXnu()
SHSTUB2(.Lape.macho.dd.skip, RVA(ape.macho) / 8);
SHSTUB2(.Lape.macho.dd.count, (.Lape.macho.end - ape.macho) / 8);
SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
#endif
#if SupportsWindows()
PFSTUB4(.Lape.pe.offset, ape.pe - ape.mz);
HIDDEN(.Lape.pe.optsz = .Lape.pe.sections - (ape.pe + 24));
HIDDEN(.Lape.pe.shnum = (.Lape.pe.sections_end - .Lape.pe.sections) / 40);
HIDDEN(.Lidata.idtsize = idata.idtend - idata.idt);
HIDDEN(.Lidata.iatsize = idata.iatend - idata.iat);
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
HIDDEN(ape_idata_idtsize = ape_idata_idtend - ape_idata_idt);
HIDDEN(ape_idata_iatsize = ape_idata_iatend - ape_idata_iat);
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage)
? kNtImageSubsystemWindowsGui
: kNtImageSubsystemWindowsCui));
@ -577,90 +543,89 @@ ZIPCONST(v_zip_commentsize, _edata - __zip_end - kZipCdirHdrMinSize);
X = (X + (Y >> 020) & 0xFF) * PHI; \
X = (X + (Y >> 030) & 0xFF) * PHI
#define CHURN(X) \
XORSHIFT(.Lape.uuid1, X); \
KMH(.Lape.uuid1, X); \
XORSHIFT(.Lape.uuid2, X); \
KMH(.Lape.uuid2, X)
HIDDEN(.Lape.uuid1 = 88172645463325252);
HIDDEN(.Lape.uuid2 = 88172645463325252);
CHURN(.Lape.bss.align);
CHURN(.Lape.bss.filesz);
CHURN(.Lape.bss.memsz);
CHURN(.Lape.bss.offset);
CHURN(.Lape.bss.paddr);
CHURN(.Lape.data.align);
CHURN(.Lape.data.filesz);
CHURN(.Lape.data.memsz);
CHURN(.Lape.data.offset);
CHURN(.Lape.data.paddr);
CHURN(.Lape.data.rva);
CHURN(.Lape.data.vaddr);
CHURN(.Lape.elf.entry);
CHURN(.Lape.elf.phnum);
CHURN(.Lape.elf.phoff);
CHURN(.Lape.elf.shnum);
CHURN(.Lape.elf.shoff);
CHURN(.Lape.elf.shstrndx);
CHURN(.Lape.macho.end);
CHURN(.Lape.note);
CHURN(.Lape.note.align);
CHURN(.Lape.note.end);
CHURN(.Lape.note.filesz);
CHURN(.Lape.note.memsz);
CHURN(.Lape.note.offset);
CHURN(.Lape.note.paddr);
CHURN(.Lape.note.vaddr);
CHURN(.Lape.ram.align);
CHURN(.Lape.ram.filesz);
CHURN(.Lape.ram.memsz);
CHURN(.Lape.ram.offset);
CHURN(.Lape.ram.paddr);
CHURN(.Lape.ram.rva);
CHURN(.Lape.ram.vaddr);
CHURN(.Lape.rom.align);
CHURN(.Lape.rom.filesz);
CHURN(.Lape.rom.memsz);
CHURN(.Lape.rom.offset);
CHURN(.Lape.rom.paddr);
CHURN(.Lape.rom.rva);
CHURN(.Lape.rom.vaddr);
CHURN(.Lape.text.align);
CHURN(.Lape.text.filesz);
CHURN(.Lape.text.memsz);
CHURN(.Lape.text.offset);
CHURN(.Lape.text.paddr);
CHURN(.Lape.text.rva);
CHURN(.Lape.text.vaddr);
XORSHIFT(ape_uuid1, X); \
KMH(ape_uuid1, X); \
XORSHIFT(ape_uuid2, X); \
KMH(ape_uuid2, X)
HIDDEN(ape_uuid1 = 88172645463325252);
HIDDEN(ape_uuid2 = 88172645463325252);
CHURN(ape_bss_align);
CHURN(ape_bss_filesz);
CHURN(ape_bss_memsz);
CHURN(ape_bss_offset);
CHURN(ape_bss_paddr);
CHURN(ape_data_filesz);
CHURN(ape_data_memsz);
CHURN(ape_data_offset);
CHURN(ape_data_paddr);
CHURN(ape_data_rva);
CHURN(ape_data_vaddr);
CHURN(ape_elf_entry);
CHURN(ape_elf_phnum);
CHURN(ape_elf_phoff);
CHURN(ape_elf_shnum);
CHURN(ape_elf_shoff);
CHURN(ape_elf_shstrndx);
CHURN(ape_macho_end);
CHURN(ape_note);
CHURN(ape_note_align);
CHURN(ape_note_end);
CHURN(ape_note_filesz);
CHURN(ape_note_memsz);
CHURN(ape_note_offset);
CHURN(ape_note_paddr);
CHURN(ape_note_vaddr);
CHURN(ape_ram_align);
CHURN(ape_ram_filesz);
CHURN(ape_ram_memsz);
CHURN(ape_ram_offset);
CHURN(ape_ram_paddr);
CHURN(ape_ram_rva);
CHURN(ape_ram_vaddr);
CHURN(ape_rom_align);
CHURN(ape_rom_filesz);
CHURN(ape_rom_memsz);
CHURN(ape_rom_offset);
CHURN(ape_rom_paddr);
CHURN(ape_rom_rva);
CHURN(ape_rom_vaddr);
CHURN(ape_text_align);
CHURN(ape_text_filesz);
CHURN(ape_text_memsz);
CHURN(ape_text_offset);
CHURN(ape_text_paddr);
CHURN(ape_text_rva);
CHURN(ape_text_vaddr);
CHURN(ADDR(.bss));
CHURN(_start);
CHURN(ape.phdrs);
CHURN(ape_phdrs);
#if SupportsMetal()
CHURN(v_ape_realsectors);
#endif
#if SupportsXnu()
CHURN(ape.macho);
CHURN(ape_macho);
#endif
#if SupportsWindows()
CHURN(ape.mz);
CHURN(ape.pe);
CHURN(.Lape.pe.offset);
CHURN(.Lape.pe.optsz);
CHURN(.Lape.pe.sections);
CHURN(.Lape.pe.sections_end);
CHURN(.Lape.pe.shnum);
CHURN(.Lape.phdrs.end);
CHURN(ape_mz);
CHURN(ape_pe);
CHURN(ape_pe_offset);
CHURN(ape_pe_optsz);
CHURN(ape_pe_sections);
CHURN(ape_pe_sections_end);
CHURN(ape_pe_shnum);
CHURN(ape_phdrs_end);
CHURN(WinMain);
#endif /* SupportsWindows() */
#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,
"__init_bss misalign");
ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
__SIZEOF_POINTER__ == 0),
"__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");
ASSERT(DEFINED(_start) || DEFINED(_start16),
@ -672,7 +637,7 @@ ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
/* Let's not be like Knight Capital. */
/* 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"); */
#endif /* __LINKER__ */

View file

@ -24,12 +24,7 @@ APELINK = \
$(COMPILE) \
$(LINK) \
$(LINKARGS) \
$(OUTPUT_OPTION) && \
$(STRIP) \
-X $@ && \
$(GZ) \
$(ZFLAGS) \
-f $@.map
$(OUTPUT_OPTION)
APE_FILES := $(wildcard ape/*.*)
APE_HDRS = $(filter %.h,$(APE_FILES))

View file

@ -22,15 +22,15 @@
#include "ape/relocations.h"
/* clang-format off */
/ Links function from external DLL.
/
/ This embeds a function pointer in the binary. The NT Executive
/ fills its value before control is handed off to the program.
/
/ @note only ELF toolchains are powerful enough to use this
/ @see libc/nt/master.sh
/ @see ape/ape.lds
/ @see winimp
// Links function from external DLL.
//
// This embeds a function pointer in the binary. The NT Executive
// fills its value before control is handed off to the program.
//
// @note only ELF toolchains are powerful enough to use this
// @see libc/nt/master.sh
// @see ape/ape.lds
// @see winimp
.macro .imp dll:req fn:req actual:req hint
.dll \dll
.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
@ -63,10 +63,10 @@
.previous
.endm
/ Defines DLL import.
/ @note this is an implementation detail of .imp
// Defines DLL import.
// @note this is an implementation detail of .imp
.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,.
.long RVA(idata.ilt.\name) # ImportLookupTable
.long 0 # TimeDateStamp
@ -76,7 +76,7 @@
.type .Lidata.idt.\name,@object
.size .Lidata.idt.\name,.-.Lidata.idt.\name
.previous
.section .idata.ro.ilt.\name\().1,"aG",\name,comdat
.section .idata.ro.ilt.\name\().1,"aG",@progbits,\name,comdat
.align __SIZEOF_POINTER__
.type idata.ilt.\name,@object
idata.ilt.\name:
@ -84,15 +84,15 @@ idata.ilt.\name:
...
decentralized content
...
*/.section .idata.ro.ilt.\name\().3,"aG",\name,comdat
*/.section .idata.ro.ilt.\name\().3,"aG",@progbits,\name,comdat
.quad 0
.previous
.section .idata.ro.hnt.\name\().1,"aG",\name,comdat
.section .idata.ro.hnt.\name\().1,"aG",@progbits,\name,comdat
.align __SIZEOF_POINTER__
.type idata.hnt.\name,@object
.equ idata.hnt.\name,.
.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__
.type idata.iat.\name,@object
idata.iat.\name:
@ -100,7 +100,7 @@ idata.iat.\name:
...
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
.previous
.section .rodata.str1.1,"aSM",@progbits,1

View file

@ -22,11 +22,11 @@
.source __FILE__
.code16
/ Resets personal computer.
/
/ @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
/ @mode real
/ @noreturn
// Resets personal computer.
//
// @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
// @mode real
// @noreturn
bootdr: push %bp
mov %sp,%bp
mov %di,%dx

View file

@ -28,7 +28,7 @@
.hidden e820map
.type e820map,@object
.size e820map,XLM_E820_SIZE
e820map = ape.xlm + XLM_E820
e820map = ape_xlm + XLM_E820
.globl e820map_xlm
.hidden e820map_xlm

View file

@ -28,7 +28,7 @@
.hidden g_ptsp
.type g_ptsp,@object
.size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE
g_ptsp = ape.xlm + XLM_PAGE_TABLE_STACK_POINTER
g_ptsp = ape_xlm + XLM_PAGE_TABLE_STACK_POINTER
.globl g_ptsp_xlm
.hidden g_ptsp_xlm

View file

@ -28,7 +28,7 @@
.hidden kBiosDataArea
.type kBiosDataArea,@object
.size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE
kBiosDataArea = ape.xlm + XLM_BIOS_DATA_AREA
kBiosDataArea = ape_xlm + XLM_BIOS_DATA_AREA
.globl kBiosDataAreaXlm
.hidden kBiosDataAreaXlm

View file

@ -63,49 +63,49 @@
#define FPU_C2 0b0000000000000010000000000
#define FPU_C3 0b0000000000100000000000000
#define CR0_PE (1u << 0) /* protected mode enabled */
#define CR0_MP (1u << 1) /* monitor coprocessor */
#define CR0_EM (1u << 2) /* no x87 fpu present if set */
#define CR0_TS (1u << 3) /* task switched x87 */
#define CR0_ET (1u << 4) /* extension type 287 or 387 */
#define CR0_NE (1u << 5) /* enable x87 error reporting */
#define CR0_WP (1u << 16) /* write protect read-only pages @pl0 */
#define CR0_AM (1u << 18) /* alignment mask */
#define CR0_NW (1u << 29) /* global write-through cache disable */
#define CR0_CD (1u << 30) /* global cache disable */
#define CR0_PG (1u << 31) /* paging enabled */
#define CR0_PE 0x01 /* protected mode enabled */
#define CR0_MP 0x02 /* monitor coprocessor */
#define CR0_EM 0x04 /* no x87 fpu present if set */
#define CR0_TS 0x08 /* task switched x87 */
#define CR0_ET 0x10 /* extension type 287 or 387 */
#define CR0_NE 0x20 /* enable x87 error reporting */
#define CR0_WP 0x00010000 /* write protect read-only pages @pl0 */
#define CR0_AM 0x00040000 /* alignment mask */
#define CR0_NW 0x20000000 /* global write-through cache disable */
#define CR0_CD 0x40000000 /* global cache disable */
#define CR0_PG 0x80000000 /* paging enabled */
#define CR4_VME (1u << 0) /* virtual 8086 mode extension */
#define CR4_PVI (1u << 1) /* protected mode virtual interrupts */
#define CR4_TSD (1u << 2) /* time stamp disable (rdtsc) */
#define CR4_DE (1u << 3) /* debugging extensions */
#define CR4_PSE (1u << 4) /* page size extension */
#define CR4_PAE (1u << 5) /* physical address extension */
#define CR4_MCE (1u << 6) /* machine check exception */
#define CR4_PGE (1u << 7) /* page global enabled */
#define CR4_OSFXSR (1u << 9) /* enable SSE and fxsave/fxrestor */
#define CR4_OSXMMEXCPT (1u << 10) /* enable unmasked SSE exceptions */
#define CR4_LA57 (1u << 12) /* enable level-5 paging */
#define CR4_VMXE (1u << 13) /* enable VMX operations */
#define CR4_SMXE (1u << 14) /* enable SMX operations */
#define CR4_FSGSBASE (1u << 16) /* enable *FSBASE and *GSBASE instructions */
#define CR4_PCIDE (1u << 17) /* enable process-context identifiers */
#define CR4_OSXSAVE (1u << 18) /* enable XSAVE */
#define CR4_VME 0x01 /* virtual 8086 mode extension */
#define CR4_PVI 0x02 /* protected mode virtual interrupts */
#define CR4_TSD 0x04 /* time stamp disable (rdtsc) */
#define CR4_DE 0x08 /* debugging extensions */
#define CR4_PSE 0x10 /* page size extension */
#define CR4_PAE 0x20 /* physical address extension */
#define CR4_MCE 0x40 /* machine check exception */
#define CR4_PGE 0x80 /* page global enabled */
#define CR4_OSFXSR 0x0200 /* enable SSE and fxsave/fxrestor */
#define CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
#define CR4_LA57 0x1000 /* enable level-5 paging */
#define CR4_VMXE 0x2000 /* enable VMX operations */
#define CR4_SMXE 0x4000 /* enable SMX operations */
#define CR4_FSGSBASE 0x00010000 /* enable *FSBASE and *GSBASE instructions */
#define CR4_PCIDE 0x00020000 /* enable process-context identifiers */
#define CR4_OSXSAVE 0x00040000 /* enable XSAVE */
#define XCR0_X87 (1u << 0)
#define XCR0_SSE (1u << 1)
#define XCR0_AVX (1u << 2)
#define XCR0_BNDREG (1u << 3)
#define XCR0_BNDCSR (1u << 4)
#define XCR0_OPMASK (1u << 5)
#define XCR0_ZMM_HI256 (1u << 6)
#define XCR0_HI16_ZMM (1u << 7)
#define XCR0_X87 0x01
#define XCR0_SSE 0x02
#define XCR0_AVX 0x04
#define XCR0_BNDREG 0x08
#define XCR0_BNDCSR 0x10
#define XCR0_OPMASK 0x20
#define XCR0_ZMM_HI256 0x40
#define XCR0_HI16_ZMM 0x80
#define EFER 0xC0000080 /* extended feature enable register */
#define EFER_SCE (1u << 0) /* system call extensions */
#define EFER_LME (1u << 8) /* long mode enable */
#define EFER_LMA (1u << 10) /* long mode active */
#define EFER_NXE (1u << 11) /* no-execute enable */
#define EFER 0xc0000080 /* extended feature enable register */
#define EFER_SCE 0x01 /* system call extensions */
#define EFER_LME 0x0100 /* long mode enable */
#define EFER_LMA 0x0400 /* long mode active */
#define EFER_NXE 0x0800 /* no-execute enable */
#define GDT_REAL_CODE 8
#define GDT_REAL_DATA 16

View file

@ -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_
#define APE_MACROS_H_
#include "libc/macros.h"
@ -8,9 +26,16 @@
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
*/
/ Calls near (i.e. pc+pcrel<64kB) FUNCTION.
/ @mode long,legacy,real
/ @cost 9 bytes overhead
// Calls function in real mode.
// It's needed because LLVM 8 LLD doesn't support R_X86_64_PC16.
.macro call16 name:req
mov $REAL(\name),%ax
call *%ax
.endm
// Calls near (i.e. pc+pcrel<64kB) FUNCTION.
// @mode long,legacy,real
// @cost 9 bytes overhead
.macro rlcall function:req
.byte 0x50 # push %[er]ax
.byte 0xb8,0,0 # mov $?,%[e]ax
@ -25,8 +50,8 @@
912:
.endm
/ Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
/ @mode long,legacy,real
// Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
// @mode long,legacy,real
.macro movesdi address:req
.byte 0xbf # mov $0x????xxxx,%[e]di
.short \address>>4
@ -39,8 +64,8 @@
297:
.endm
/ Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
/ @mode long,legacy,real
// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
// @mode long,legacy,real
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
.ifnb \abcd
.if (\constexpr)<128 && (\constexpr)>=0
@ -52,8 +77,8 @@
movb $(\constexpr)&0xff,\abcd.lo
.endm
/ Compares 16-bit CONSTEXPR with Qw-register.
/ @mode long,legacy,real
// Compares 16-bit CONSTEXPR with Qw-register.
// @mode long,legacy,real
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
cmpb $(\constexpr)>>8&0xff,\abcd.hi
jnz 387f
@ -61,8 +86,8 @@
387:
.endm
/ Adds 16-bit CONSTEXPR to Qw-register.
/ @mode long,legacy,real
// Adds 16-bit CONSTEXPR to Qw-register.
// @mode long,legacy,real
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
addb $(\constexpr)&0xff,\abcd.lo
.if (\constexpr) != 0
@ -70,8 +95,8 @@
.endif
.endm
/ Subtracts 16-bit CONSTEXPR from Qw-register.
/ @mode long,legacy,real
// Subtracts 16-bit CONSTEXPR from Qw-register.
// @mode long,legacy,real
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
subb $(\constexpr)&0xff,\abcd.lo
.if (\constexpr) != 0
@ -79,8 +104,8 @@
.endif
.endm
/ Ands Qw-register with 16-bit CONSTEXPR.
/ @mode long,legacy,real
// Ands Qw-register with 16-bit CONSTEXPR.
// @mode long,legacy,real
.macro bband constexpr:req abcd.hi:req abcd.lo:req
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
andb $(\constexpr)&0xff,\abcd.lo
@ -90,8 +115,8 @@
.endif
.endm
/ Ors Qw-register with 16-bit CONSTEXPR.
/ @mode long,legacy,real
// Ors Qw-register with 16-bit CONSTEXPR.
// @mode long,legacy,real
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
orb $(\constexpr)&0xff,\abcd.lo
@ -101,8 +126,8 @@
.endif
.endm
/ Performs ACTION only if in real mode.
/ @mode long,legacy,real
// Performs ACTION only if in real mode.
// @mode long,legacy,real
.macro rlo clobber:req action:vararg
990: mov $0,\clobber
.if .-990b!=3
@ -117,10 +142,10 @@
.endif
.endm
/ Initializes real mode stack.
/ The most holiest of holy code.
/ @mode real
/ @see www.pcjs.org/pubs/pc/reference/intel/8086/
// Initializes real mode stack.
// The most holiest of holy code.
// @mode real
// @see www.pcjs.org/pubs/pc/reference/intel/8086/
.macro rlstack seg:req addr:req
cli
mov \seg,%ss
@ -128,7 +153,7 @@
sti
.endm
/ Symbolic Linker-Defined Binary Content.
// Symbolic Linker-Defined Binary Content.
.macro .stub name:req kind:req default type=@object
.ifnb \default
.equ \name,\default
@ -139,17 +164,17 @@
.hidden \name
.endm
/ Symbolic Linker-Defined Binary-Encoded-Bourne Content.
/ @param units is the number of encoded 32-bit values to insert,
/ e.g. \000 can be encoded as 0x3030305c.
.macro .shstub name:req units:req
// Symbolic Linker-Defined Binary-Encoded-Bourne Content.
// @param units is the number of encoded 32-bit values to insert,
// e.g. \000 can be encoded as 0x3030305c.
.macro .shstub name:req num:req
ss \name,0
.if \units>1
.if \num>1
ss \name,1
.if \units>2
.if \num>2
ss \name,2
ss \name,3
.if \units>4
.if \num>4
ss \name,4
ss \name,5
ss \name,6
@ -166,8 +191,8 @@
#elif defined(__LINKER__)
#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_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((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 BCXSTUB(SYM, X) \
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \

View file

@ -15,16 +15,16 @@
# build/archive rcsD library.a foo.o ...
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
# if [ -x "o/$MODE/tool/build/ar.com" ]; then
# set -- "o/$MODE/tool/build/ar.com" "$@"
# else
if [ ! -x o/build/bootstrap/ar.com ]; then
mkdir -p o/build/bootstrap &&
cp -f build/bootstrap/ar.com o/build/bootstrap/ar.com.$$ &&
mv -f o/build/bootstrap/ar.com.$$ o/build/bootstrap/ar.com || exit
if [ -x "o//tool/build/ar.com" ]; then
set -- "o//tool/build/ar.com" "$@"
else
if [ ! -x o/build/bootstrap/ar.com ]; then
mkdir -p o/build/bootstrap &&
cp -f build/bootstrap/ar.com o/build/bootstrap/ar.com.$$ &&
mv -f o/build/bootstrap/ar.com.$$ o/build/bootstrap/ar.com || exit
fi
set -- o/build/bootstrap/ar.com "$@"
fi
set -- o/build/bootstrap/ar.com "$@"
# fi
OUT=$3
printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -20,8 +20,6 @@ CONFIG_CCFLAGS += \
TARGET_ARCH ?= \
-msse3
RAGELFLAGS ?= -G2
endif
# Optimized Mode
@ -48,8 +46,6 @@ CONFIG_CCFLAGS += \
TARGET_ARCH ?= \
-march=native
RAGELFLAGS ?= -G2
endif
# Release Mode
@ -73,8 +69,6 @@ CONFIG_CCFLAGS += \
$(BACKTRACES) \
-O2
RAGELFLAGS = -G2
endif
# Debug Mode
@ -247,6 +241,23 @@ TARGET_ARCH ?= \
-msse3
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
#
# These flags cause GCC to predefine __STRICT_ANSI__. Please be warned

View file

@ -197,17 +197,15 @@ DEFAULT_LDFLAGS = \
-static \
-nostdlib \
-m elf_x86_64 \
--gc-sections \
--build-id=none \
--cref -Map=$@.map \
--no-dynamic-linker \
-z max-page-size=0x1000 \
-Ttext-segment=$(IMAGE_BASE_VIRTUAL)
-z max-page-size=0x1000
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)
ASONLYFLAGS = \
-c \
-g \
--debug-prefix-map="$(PWD)"=
@ -313,7 +311,7 @@ OBJECTIFY.c = $(CC) $(OBJECTIFY.c.flags) -c
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
PREPROCESS = $(CC) $(PREPROCESS.flags)
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
LINK = build/link $(LD) $(LINK.flags)
LINK = $(LD) $(LINK.flags)
ELF = o/libc/elf/elf.lds
ELFLINK = ACTION=LINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
ARCHIVE = $(AR) $(ARFLAGS)

View file

@ -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/$(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: o/$(MODE)/%.s; @TARGET=$@ $(COMPILE) $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
o/$(MODE)/%.s: %.S; @ACTION=PREPROCESS $(COMPILE) $(PREPROCESS) $(OUTPUT_OPTION) $<

View file

@ -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
"$@"
rc=$?
echo "$1"
$DD if="$1.bak" of="$1" bs=4096 count=1 conv=notrunc 2>/dev/null
exit $rc

View file

@ -20,18 +20,18 @@
#define BIAS 0x84
/ Encodes audio sample with µ-Law.
/
/ This is both the highest quality and most widely supported
/ telephony codec, whose use was phased out in the 2000's in
/ favor of cost-saving GSM audio compression that was so bad
/ consumers were willing to pay more cash, for the privilege
/ of saving telcos even more money w/ text messaging. Mu Law
/ reduces PCM data to half its original size, by diminishing
/ audio bands not vocalized by human voice.
/
/ @param %edi is pcm sample
/ @return %eax is uint8_t encoded sample
// Encodes audio sample with µ-Law.
//
// This is both the highest quality and most widely supported
// telephony codec, whose use was phased out in the 2000's in
// favor of cost-saving GSM audio compression that was so bad
// consumers were willing to pay more cash, for the privilege
// of saving telcos even more money w/ text messaging. Mu Law
// reduces PCM data to half its original size, by diminishing
// audio bands not vocalized by human voice.
//
// @param %edi is pcm sample
// @return %eax is uint8_t encoded sample
mulaw: .leafprologue
.profilable
mov $BIAS,%eax

View file

@ -19,11 +19,11 @@
#include "libc/macros.h"
.align 16
/ Mixes audio.
/
/ @param rdi is # aligned int16[16] sample chunks to process
/ @param rsi points to aligned pcm s16le input/output memory
/ @param rdx points to aligned pcm s16le [0..1] input memory
// Mixes audio.
//
// @param rdi is # aligned int16[16] sample chunks to process
// @param rsi points to aligned pcm s16le input/output memory
// @param rdx points to aligned pcm s16le [0..1] input memory
sad16x8n:
.leafprologue
.profilable

View file

@ -18,7 +18,7 @@
*/
#include "libc/macros.h"
/ TODO(jart): write me
// TODO(jart): write me
movdqa a,%xmm0
mpsadbw $0,inv,%xmm0

View file

@ -19,11 +19,11 @@
#include "libc/macros.h"
.source __FILE__
/ Returns index of minimum uint16 in array.
/
/ @param rdi points to nonempty array
/ @param rsi is item count divisible by 16
/ @note needs avx2 (haswell+)
// Returns index of minimum uint16 in array.
//
// @param rdi points to nonempty array
// @param rsi is item count divisible by 16
// @note needs avx2 (haswell+)
windex_avx2:
push %rbp
mov %rsp,%rbp

View file

@ -19,11 +19,11 @@
#include "libc/macros.h"
.source __FILE__
/ Returns index of minimum positive int16 in array.
/
/ @param rdi points to nonempty array
/ @param esi is 16-byte aligned 8+ / 8 multiple array item count
/ @note needs sse4 (nehalem+)
// Returns index of minimum positive int16 in array.
//
// @param rdi points to nonempty array
// @param esi is 16-byte aligned 8+ / 8 multiple array item count
// @note needs sse4 (nehalem+)
windex_sse4:
push %rbp
mov %rsp,%rbp

View file

@ -20,7 +20,7 @@
#include "libc/macros.h"
.source __FILE__
/ Dispatches to fastest windex() implementation.
// Dispatches to fastest windex() implementation.
.initbss 300,_init_windex
windex: .quad 0
.endobj windex,globl

View file

@ -48,6 +48,6 @@ int main(int argc, char *argv[]) {
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],
g_log.x()[0], g_log.x()[0]);
delete x;
delete[] x;
return 0;
}

View file

@ -1,13 +1,13 @@
#include "libc/macros.h"
/ Example assembly function.
/
/ @note param agnostic
/ @note we love stack frames
/ easiest way to do backtraces
/ somehow they usually make code faster
/ it's convention for keeping stack 16-byte aligned
/ cpus still devote much to pushing & popping b/c i386
// Example assembly function.
//
// @note param agnostic
// @note we love stack frames
// easiest way to do backtraces
// somehow they usually make code faster
// it's convention for keeping stack 16-byte aligned
// cpus still devote much to pushing & popping b/c i386
MyAsm: push %rbp
mov %rsp,%rbp
call MyPrint2

View file

@ -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__

View file

@ -4,27 +4,8 @@
#include "libc/mem/mem.h"
#include "libc/str/str.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if 0
/**
* @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
/* TOOD(jart): DELETE */
#define append(ARRAYLIST, ITEM) concat((ARRAYLIST), (ITEM), 1)
@ -38,7 +19,7 @@
size_t Idx = List->i; \
if (Idx + Count < List->n || __grow(&List->p, &List->n, SizE, Count)) { \
memcpy(&List->p[Idx], Item, SizE *Count); \
atomic_store(&List->i, Idx + Count); \
List->i = Idx + Count; \
} else { \
Idx = -1UL; \
} \

View file

@ -234,12 +234,10 @@ intptr_t atomic_store(void *, intptr_t, size_t);
* @return LOCALVAR[0]
* @see xchg()
*/
#define lockxchg(MEMORY, LOCALVAR) \
({ \
_Static_assert( \
__builtin_types_compatible_p(typeof(*(MEMORY)), typeof(*(LOCALVAR)))); \
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
*(LOCALVAR); \
#define lockxchg(MEMORY, LOCALVAR) \
({ \
asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
*(LOCALVAR); \
})
/**

View file

@ -1,5 +1,6 @@
#ifndef 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/rlimit.h"
#include "libc/calls/struct/rusage.h"
@ -62,7 +63,6 @@ COSMOPOLITAN_C_START_
*/
typedef int sig_atomic_t;
typedef struct dirstream DIR;
extern const struct sigset kSigsetFull;
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 faccessat(int, const char *, int, uint32_t);
int fadvise(int, uint64_t, uint64_t, int);
int fallocate(int, int32_t, int64_t, int64_t);
int fchmod(int, uint32_t) nothrow;
int fchmodat(int, const char *, 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 pipe2(int[hasatleast 2], 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 raise(int);
int readlink(const char *, char *, size_t);

View file

@ -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();
}
}
}

View file

@ -29,7 +29,6 @@
* since the prior extends logically and the latter physically
* @return 0 on success, or -1 w/ errno
* @asyncsignalsafe
* @see fallocate()
*/
int ftruncate(int fd, int64_t length) {
if (!IsWindows()) {

View file

@ -19,13 +19,13 @@
#include "libc/macros.h"
.source __FILE__
/ Obtains WIN32 magic path, e.g. GetTempPathA.
/
/ @param rax is address of ANSI path provider function
/ @param rdi is output buffer
/ @param rdx is output buffer size in bytes that's >0
/ @return eax is string length w/ NUL that's ≤ edx
/ @return rdi is rdi+edx
// Obtains WIN32 magic path, e.g. GetTempPathA.
//
// @param rax is address of ANSI path provider function
// @param rdi is output buffer
// @param rdx is output buffer size in bytes that's >0
// @return eax is string length w/ NUL that's ≤ edx
// @return rdi is rdi+edx
.text.startup
__getntsyspath:
push %rbp
@ -40,14 +40,14 @@ __getntsyspath:
cmovbe %edx,%eax
cmp $1,%eax # leave empty strings empty
jbe 1f
cmpb $'\\,-1(%rdi,%rax) # guarantee trailing slash
cmpb $'\\',-1(%rdi,%rax) # guarantee trailing slash
je 1f
movw $'\\,(%rdi,%rax)
movw $'\\',(%rdi,%rax)
inc %eax
1: inc %rdi # change backslash to slash
cmpb $'\\,-1(%rdi)
cmpb $'\\',-1(%rdi)
jne 2f
movb $'/,-1(%rdi)
movb $'/',-1(%rdi)
2: .loop 1b
leave
ret

View file

@ -22,8 +22,8 @@
#include "libc/sysv/errfuns.h"
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 (who && abs(who) != getpid() && abs(who) != gettid()) return eopnotsupp();
if (who && who != getpid() && who != gettid()) return eopnotsupp();
return impl(value);
}

View file

@ -19,9 +19,9 @@
#include "libc/macros.h"
.source __FILE__
/ Calls GetTempPathA() w/ different API.
/
/ @see GetSystemDirectoryA(), GetWindowsDirectoryA()
// Calls GetTempPathA() w/ different API.
//
// @see GetSystemDirectoryA(), GetWindowsDirectoryA()
GetTempPathA_flunk:
xchg %rcx,%rdx
jmp *__imp_GetTempPathA(%rip)

View file

@ -120,7 +120,6 @@ i32 sys_dup3(i32, i32, i32) hidden;
i32 sys_execve(const char *, char *const[], char *const[]) hidden;
i32 sys_faccessat(i32, const char *, i32, u32) hidden;
i32 sys_fadvise(i32, i64, i64, i32) hidden;
i32 sys_fallocate(i64, i32, i64, i64) hidden;
i32 sys_fchdir(i32) hidden;
i32 sys_fchmod(i32, 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_pipe(i32[hasatleast 2]) 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_renameat(i32, const char *, i32, const char *) 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);
void WinMainForked(void) 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;
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;

View file

@ -22,9 +22,9 @@
#define BYTES 64
/ RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
/
/ @note guarantees trailing slash if non-empty
// RII constant holding 'C:/WINDOWS/SYSTEM32' directory.
//
// @note guarantees trailing slash if non-empty
.initbss 300,_init_kNtSystemDirectory
kNtSystemDirectory:
.zero BYTES

View file

@ -22,9 +22,9 @@
#define BYTES 64
/ RII constant holding 'C:/WINDOWS' directory.
/
/ @note guarantees trailing slash if non-empty
// RII constant holding 'C:/WINDOWS' directory.
//
// @note guarantees trailing slash if non-empty
.initbss 300,_init_kNtWindowsDirectory
kNtWindowsDirectory:
.zero BYTES

View file

@ -22,10 +22,10 @@
#define kTmpPathMax 80
/ RII constant holding /tmp/ directory.
/
/ @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
/ @note guarantees trailing slash if non-empty
// RII constant holding /tmp/ directory.
//
// @note on win32 this is firstNonNull($TMP, $TEMP, $PWD)
// @note guarantees trailing slash if non-empty
.initbss 300,_init_kTmpPath
kTmpPath:
.zero kTmpPathMax
@ -33,8 +33,8 @@ kTmpPath:
.previous
.init.start 300,_init_kTmpPath
movl $'/|'t<<010|'m<<020|'p<<030,(%rdi)
movw $'/,4(%rdi)
movl $'/'|'t'<<010|'m'<<020|'p'<<030,(%rdi)
movw $'/',4(%rdi)
#if SupportsWindows()
pushpop kTmpPathMax,%rdx
ezlea GetTempPathA_flunk,ax

View file

@ -19,10 +19,10 @@
#include "libc/nexgen32e/x86feature.h"
#include "libc/macros.h"
/ Returns timestamp without needing system calls.
/
/ @return seconds since unix epoch in %st0
/ @note uses microsecond scale fallback on k8 or vm
// Returns timestamp without needing system calls.
//
// @return seconds since unix epoch in %st0
// @note uses microsecond scale fallback on k8 or vm
.initbss 202,_init_nowl
nowl: .quad 0
.endobj nowl,globl

View file

@ -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);
}

View file

@ -19,18 +19,19 @@
#include "libc/calls/calls.h"
#include "libc/calls/termios.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/errfuns.h"
errno_t ptsname_r(int fd, char *buf, size_t size) {
int pty;
char tb[32];
if (size) {
if (!buf) return einval();
if (ioctl(fd, TIOCGPTN, &pty) == -1) return errno;
if (snprintf(buf, size, "/dev/pts/%d", pty) >= size) {
return (errno = ERANGE);
}
int64toarray_radix10(pty, stpcpy(tb, "/dev/pts/"));
if (strlen(tb) + 1 >= size) return (errno = ERANGE);
stpcpy(buf, tb);
/* TODO(jart): OpenBSD OMG */
}
return 0;

View file

@ -19,10 +19,10 @@
#include "libc/macros.h"
.source __FILE__
/ Sets effective group ID.
/
/ @param %edi is group id
/ @see setgid(), getauxval(AT_SECURE)
// Sets effective group ID.
//
// @param %edi is group id
// @see setgid(), getauxval(AT_SECURE)
setegid:push %rbp
mov %rsp,%rbp
.profilable

View file

@ -19,10 +19,10 @@
#include "libc/macros.h"
.source __FILE__
/ Sets effective user ID.
/
/ @param %edi is user id
/ @see setuid(), getauxval(AT_SECURE)
// Sets effective user ID.
//
// @param %edi is user id
// @see setuid(), getauxval(AT_SECURE)
seteuid:push %rbp
mov %rsp,%rbp
.profilable

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
@ -134,15 +135,15 @@ static void sigaction_native2cosmo(union metasigaction *sa) {
* @vforksafe
*/
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;
int rc, rva, oldrva;
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 (!(0 < sig && sig < NSIG)) return einval();
if (sig == SIGKILL || sig == SIGSTOP) return einval();

View file

@ -20,16 +20,16 @@
#include "libc/macros.h"
.source __FILE__
/ BSD signal handler.
/
/ This is needed because (1) a signal is allowed to trigger at
/ just about any time, and leaf functions (e.g. memcpy) aren't
/ required to leave Cosmopolitan's image base register alone.
/
/ @param %edi is the signal number
/ @param %rsi will be passed for sigactions
/ @param %rdx will be passed for sigactions
/ @return true if handler was invoked
// BSD signal handler.
//
// This is needed because (1) a signal is allowed to trigger at
// just about any time, and leaf functions (e.g. memcpy) aren't
// required to leave Cosmopolitan's image base register alone.
//
// @param %edi is the signal number
// @param %rsi will be passed for sigactions
// @param %rdx will be passed for sigactions
// @return true if handler was invoked
__sigenter:
push %rbp
mov %rsp,%rbp

View file

@ -10,5 +10,8 @@ struct dirent { /* linux getdents64 abi */
char d_name[256]; /* NUL-terminated basename */
};
struct dirstream;
typedef struct dirstream DIR;
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_DIRENT_H_ */

View file

@ -21,6 +21,7 @@
#include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h"
#include "libc/log/log.h"
#include "libc/nt/console.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;
if (!isatty(fd)) return errno;
char name[PATH_MAX];
snprintf(name, sizeof(name), "/proc/self/fd/%d", fd);
int64toarray_radix10(fd, stpcpy(name, "/proc/self/fd/"));
ssize_t got;
got = readlink(name, buf, size);
if (got == -1) return errno;

View file

@ -4,7 +4,5 @@
typedef void (*sighandler_t)(int);
typedef void (*sighandler_t)(int);
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_TYPEDEF_SIGHANDLER_T_H_ */

View file

@ -23,11 +23,11 @@
.section .start,"ax",@progbits
.align 16
/ System Five userspace program entrypoint.
/
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
/ @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
/ @noreturn
// System Five userspace program entrypoint.
//
// @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
// @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
// @noreturn
_start:
#if SupportsFreebsd()
test %rdi,%rdi
@ -39,12 +39,12 @@ _start:
lea 8(%rsp),%rsi # argv
lea 24(%rsp,%rbx,8),%rdx # envp
.frame0
/ bofram 9f
.weak idata.iat
.weak idata.iatend
// bofram 9f
.weak ape_idata_iat
.weak ape_idata_iatend
ezlea missingno,ax # make win32 imps noop
ezlea idata.iat,di
ezlea idata.iatend,cx
ezlea ape_idata_iat,di
ezlea ape_idata_iatend,cx
sub %rdi,%rcx
shr $3,%ecx
rep stosq
@ -70,11 +70,11 @@ _start:
.endfn _start,weak,hidden
#if SupportsXnu()
/ Macintosh userspace program entrypoint.
/
/ @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
/ @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
/ @noreturn
// Macintosh userspace program entrypoint.
//
// @param rsp is [n,argv₀..argvₙ₋₁,0,envp₀..,0,auxv₀..,0,..]
// @note FreeBSD is special (see freebsd/lib/csu/amd64/...)
// @noreturn
_xnu: movb $XNU,__hostos(%rip)
jmp 0b
.endfn _xnu,weak,hidden

View file

@ -13,10 +13,8 @@ struct DnsHeader {
uint16_t arcount; /* additional record count */
};
int serializednsheader(uint8_t *buf, size_t size,
const struct DnsHeader header);
int deserializednsheader(struct DnsHeader *header, const uint8_t *buf,
size_t size);
int serializednsheader(uint8_t *, size_t, const struct DnsHeader);
int deserializednsheader(struct DnsHeader *, const uint8_t *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -54,7 +54,11 @@ static textwindows noinline char *getnthoststxtpath(char *pathbuf,
* @note yoinking realloc() ensures there's no size limits
*/
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) {
g_hoststxt = &init->ht;
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.p = init->strings;
__cxa_atexit(freehoststxt, &g_hoststxt, NULL);
char pathbuf[PATH_MAX];
const char *path = "/etc/hosts";
path = "/etc/hosts";
if (IsWindows()) {
path = firstnonnull(getnthoststxtpath(pathbuf, ARRAYLEN(pathbuf)), path);
}
FILE *f;
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);
sorthoststxt(g_hoststxt);

View file

@ -55,7 +55,7 @@ const struct ResolvConf *getresolvconf(void) {
rc = getntnameservers(g_resolvconf);
}
if (rc == -1 && !IsTiny()) {
fprintf(stderr, "%s: %m\n", "nameserver discovery failed");
/* TODO(jart): Elevate robustness. */
}
}
return g_resolvconf;

View file

@ -18,15 +18,20 @@
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/str/str.h"
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
char *name;
Elf64_Half i;
Elf64_Shdr *shdr;
for (i = elf->e_shnum; i > 0; --i) {
if (i - 1 == elf->e_shstrndx) continue;
shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1);
for (i = 0; i < elf->e_shnum; ++i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i);
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;

View file

@ -17,7 +17,6 @@ COSMOPOLITAN_C_START_
int abs(int) libcesque pureconst;
long labs(long) libcesque pureconst;
long long llabs(long long) libcesque pureconst;
char *ltpcpy(char *, long) paramsnonnull() libcesque nocallback;
int llog10(unsigned long) libcesque pureconst;
int atoi(const char *) paramsnonnull() libcesque;
long atol(const char *) paramsnonnull() libcesque;

View file

@ -26,7 +26,7 @@
* @param a needs at least 21 bytes
* @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;
j = 0;
do {
@ -43,7 +43,7 @@ noinline size_t uint64toarray_radix10(uint64_t i, char *a) {
* @param a needs at least 21 bytes
* @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);
*a++ = '-';
return 1 + uint64toarray_radix10(-i, a);

View file

@ -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;
}

View file

@ -129,7 +129,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
int w, flags, width, lasterr, precision;
lasterr = errno;
out = fn ? fn : (int (*)(int, void *))missingno;
out = fn ? fn : (void *)missingno;
while (*format) {
/* %[flags][width][.precision][length] */
@ -267,9 +267,8 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
case 'u': {
flags &= ~FLAGS_HASH; /* no hash for dec format */
DoNumber:
if (!weaken(ntoa) ||
weaken(ntoa)(out, arg, va, signbit, log2base, precision, width,
flags, alphabet) == -1) {
if (ntoa(out, arg, va, signbit, log2base, precision, width, flags,
alphabet) == -1) {
return -1;
}
break;
@ -282,8 +281,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
} else {
ldbl = va_arg(va, double);
}
if (!weaken(ftoa) ||
weaken(ftoa)(out, arg, ldbl, precision, width, flags) == -1) {
if (ftoa(out, arg, ldbl, precision, width, flags) == -1) {
return -1;
}
break;
@ -312,8 +310,7 @@ hidden int palandprintf(void *fn, void *arg, const char *format, va_list va) {
case 's':
p = va_arg(va, void *);
showstr:
if (!weaken(stoa) || weaken(stoa)(out, arg, p, flags, precision, width,
signbit, qchar) == -1) {
if (stoa(out, arg, p, flags, precision, width, signbit, qchar) == -1) {
return -1;
}
break;

View file

@ -17,22 +17,19 @@
* format strings are constexprs that only contain directives.
*/
#define PFLINK(FMT) \
({ \
if (___PFLINK(FMT, strpbrk, "bxdinupo")) STATIC_YOINK("ntoa"); \
if (___PFLINK(FMT, strpbrk, "fFgGaA")) STATIC_YOINK("ftoa"); \
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
STATIC_YOINK("stoa"); \
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
___PFLINK(FMT, strpbrk, "0123456789"))) { \
STATIC_YOINK("strnwidth"); \
STATIC_YOINK("strnwidth16"); \
STATIC_YOINK("wcsnwidth"); \
} \
} \
FMT; \
#define PFLINK(FMT) \
({ \
if (___PFLINK(FMT, strpbrk, "cmrqs")) { \
if (___PFLINK(FMT, strchr, '#')) STATIC_YOINK("kCp437"); \
if (___PFLINK(FMT, strstr, "%m")) STATIC_YOINK("strerror"); \
if (!IsTiny() && (___PFLINK(FMT, strstr, "%*") || \
___PFLINK(FMT, strpbrk, "0123456789"))) { \
STATIC_YOINK("strnwidth"); \
STATIC_YOINK("strnwidth16"); \
STATIC_YOINK("wcsnwidth"); \
} \
} \
FMT; \
})
#define SFLINK(FMT) \
@ -40,7 +37,7 @@
if (___PFLINK(FMT, strchr, 'm')) { \
STATIC_YOINK("malloc"); \
STATIC_YOINK("calloc"); \
STATIC_YOINK("free_s"); \
STATIC_YOINK("free"); \
STATIC_YOINK("__grow"); \
} \
FMT; \
@ -70,8 +67,6 @@
#define SFLINK(FMT) FMT
#ifdef __GNUC__
__asm__(".section .yoink\n\t"
"nopl\tntoa(%rip)\n\t"
"nopl\tftoa(%rip)\n\t"
"nopl\tkCp437(%rip)\n\t"
"nopl\tstrerror(%rip)\n\t"
"nopl\tstrnwidth(%rip)\n\t"
@ -79,14 +74,11 @@ __asm__(".section .yoink\n\t"
"nopl\twcsnwidth(%rip)\n\t"
"nopl\tmalloc(%rip)\n\t"
"nopl\tcalloc(%rip)\n\t"
"nopl\tfree_s(%rip)\n\t"
"nopl\t__grow(%rip)\n\t"
".previous");
#else
static long __pflink(long x) {
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 |= strnwidth16(0, 0, 0);
x |= wcsnwidth(0, 0, 0);
@ -94,7 +86,6 @@ static long __pflink(long x) {
x |= __grow(0, 0, 0, 0);
x |= (intptr_t)strerror(0);
x |= (intptr_t)calloc(0, 0);
free_s(0);
return x;
}
#endif

View file

@ -26,6 +26,9 @@
#include "libc/nt/runtime.h"
#include "libc/str/str.h"
STATIC_YOINK("ntoa");
STATIC_YOINK("stoa");
STATIC_YOINK("E2BIG");
STATIC_YOINK("EACCES");
STATIC_YOINK("EADDRINUSE");
@ -321,7 +324,7 @@ int strerror_r(int err, char *buf, size_t size) {
s = firstnonnull(geterrname(err), "?");
}
if (!SupportsWindows()) {
snprintf(buf, size, "E%s[%d]", s, err);
(snprintf)(buf, size, "E%s[%d]", s, err);
} else {
winstate = GetLastError();
sysvstate = errno;
@ -332,8 +335,8 @@ int strerror_r(int err, char *buf, size_t size) {
} else {
buf16[0] = u'\0';
}
snprintf(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
sysvstate, winstate, buf16[0] ? " " : "", buf16);
(snprintf)(buf, size, "E%s/err=%d/errno:%d/GetLastError:%d%s%hs", s, err,
sysvstate, winstate, buf16[0] ? " " : "", buf16);
}
return 0;
}

View file

@ -286,13 +286,11 @@ int vcscanf(int callback(void *), int unget(int, void *), void *arg,
}
}
Done:
while (freeme) {
while (freeme && weaken(free)) {
struct FreeMe *entry = freeme;
freeme = entry->next;
if (items == -1) {
weaken(free_s)((void **)&entry->ptr);
}
weaken(free_s)((void **)&entry);
if (items == -1) weaken(free)(entry->ptr);
weaken(free)(entry);
}
return items;
}

View file

@ -67,22 +67,6 @@
} while (0)
#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__)
#define _Atomic(TYPE) TYPE
#endif
@ -652,7 +636,7 @@ typedef uint64_t uintmax_t;
#endif
#ifndef _Section
#ifndef __STRICT_ANSI__
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define _Section(s) __attribute__((__section__(s)))
#else
#define _Section(s)
@ -667,16 +651,17 @@ typedef uint64_t uintmax_t;
#ifndef __STRICT_ANSI__
#if defined(__GNUC__) || defined(__llvm__)
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
#pragma GCC diagnostic ignored "-Wsign-compare" /* lint needs to change */
#pragma GCC diagnostic ignored "-Wtype-limits" /* makes macros unsafe */
#pragma GCC diagnostic ignored "-Woverflow" /* also breaks macros */
#pragma GCC diagnostic ignored "-Wformat" /* forces only gnu pf */
#pragma GCC diagnostic ignored "-Wunused-parameter" /* extreme prejudice */
#pragma GCC diagnostic ignored "-Wunused-function" /* contradicts dce! */
#pragma GCC diagnostic ignored "-Wunused-variable" /* belongs in tidy */
#pragma GCC diagnostic ignored "-Wformat-extra-args" /* is also broken */
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
#pragma GCC diagnostic ignored "-Wparentheses" /* annoying tidy */
#pragma GCC diagnostic ignored "-Wdangling-else" /* come on tidy */
#pragma GCC diagnostic ignored "-Wformat-security" /* come on tidy */
#ifndef __cplusplus
#pragma GCC diagnostic ignored "-Wimplicit-int"
#endif /* C++ */
@ -704,8 +689,8 @@ typedef uint64_t uintmax_t;
"-Wincompatible-pointer-types-discards-qualifiers"
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
#pragma clang diagnostic ignored "-Wparentheses-equality" /*-save-temps*/
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
#pragma clang diagnostic ignored "-Wunused-value" /*({-save-temps})*/
#pragma clang diagnostic ignored "-Wstring-plus-int" /* special ed */
#pragma clang diagnostic ignored "-Wunused-value" /* extreme prejudice */
#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
#pragma clang diagnostic ignored \
@ -797,22 +782,14 @@ typedef uint64_t uintmax_t;
#define EXPROPRIATE(EXPRESSION) (EXPRESSION)
#endif
#ifndef __STRICT_ANSI__
#define YOINK(SYMBOL) \
do { \
_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)
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define YOINK(SYMBOL) \
asm(".section .yoink\n\tnopl\t%a0\n\t.previous" : : "X"(SYMBOL))
#else
#define YOINK(SYMBOL) (void)0
#endif
#ifndef __STRICT_ANSI__
#if !defined(__STRICT_ANSI__) && !defined(__APPLE__)
#define STATIC_YOINK(SYMBOLSTR) \
asm(".section .yoink\n\tnopl\t\"" SYMBOLSTR "\"\n\t.previous")
#else

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥+𝑦, aborting on overflow.
/
/ @param rdi is int64 𝑥
/ @param rsi is int64 𝑦
/ @return rax is 𝑥+𝑦
/ @see -ftrapv
// Returns 𝑥+𝑦, aborting on overflow.
//
// @param rdi is int64 𝑥
// @param rsi is int64 𝑦
// @return rax is 𝑥+𝑦
// @see -ftrapv
__addvdi3:
mov %rdi,%rax
add %rsi,%rax

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥+𝑦, aborting on overflow.
/
/ @param edi is int32 𝑥
/ @param esi is int32 𝑦
/ @return eax is 𝑥+𝑦
/ @see -ftrapv
// Returns 𝑥+𝑦, aborting on overflow.
//
// @param edi is int32 𝑥
// @param esi is int32 𝑦
// @return eax is 𝑥+𝑦
// @see -ftrapv
__addvsi3:
mov %edi,%eax
add %esi,%eax

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥+𝑦, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @param rdx:rcx is int128 𝑦
/ @return rdx:rax is 𝑥+𝑦
/ @see -ftrapv
// Returns 𝑥+𝑦, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @param rdx:rcx is int128 𝑦
// @return rdx:rax is 𝑥+𝑦
// @see -ftrapv
__addvti3:
mov %rdi,%rax
add %rdx,%rax

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Jump table for mpsadbw() with non-constexpr immediate parameter.
/
/ @note needs sse4 cf. core c. 2006 cf. bulldozer c. 2011
/ @see mpsadbw()
// Jump table for mpsadbw() with non-constexpr immediate parameter.
//
// @note needs sse4 cf. core c. 2006 cf. bulldozer c. 2011
// @see mpsadbw()
.align 8
__mpsadbws:
i = 0

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥*𝑦, aborting on overflow.
/
/ @param rdi is int64 𝑥
/ @param rdi is int64 𝑦
/ @return rax is 𝑥*𝑦
/ @see -ftrapv
// Returns 𝑥*𝑦, aborting on overflow.
//
// @param rdi is int64 𝑥
// @param rdi is int64 𝑦
// @return rax is 𝑥*𝑦
// @see -ftrapv
__mulvdi3:
mov %rdi,%rax
imul %rsi

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥*𝑦, aborting on overflow.
/
/ @param edi is int32 𝑥
/ @param esi is int32 𝑦
/ @return eax is 𝑥*𝑦
/ @see -ftrapv
// Returns 𝑥*𝑦, aborting on overflow.
//
// @param edi is int32 𝑥
// @param esi is int32 𝑦
// @return eax is 𝑥*𝑦
// @see -ftrapv
__mulvsi3:
mov %edi,%eax
imul %esi

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥*𝑦, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @param rdx:rcx is int128 𝑦
/ @return rdx:rax is 𝑥*𝑦
/ @see -ftrapv
// Returns 𝑥*𝑦, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @param rdx:rcx is int128 𝑦
// @return rdx:rax is 𝑥*𝑦
// @see -ftrapv
__mulvti3:
push %rbp
mov %rsp,%rbp

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns -𝑥, aborting on overflow (two's complement bane).
/
/ @param rdi is int64 𝑥
/ @return rax is -𝑥
/ @see -ftrapv
// Returns -𝑥, aborting on overflow (two's complement bane).
//
// @param rdi is int64 𝑥
// @return rax is -𝑥
// @see -ftrapv
__negvdi2:
mov %rdi,%rax
neg %rax

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns -𝑥, aborting on overflow (two's complement bane).
/
/ @param edi is int32 𝑥
/ @return eax is -𝑥
/ @see -ftrapv
// Returns -𝑥, aborting on overflow (two's complement bane).
//
// @param edi is int32 𝑥
// @return eax is -𝑥
// @see -ftrapv
__negvsi2:
mov %edi,%eax
neg %eax

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns -𝑥, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @return rdx:rax is -𝑥
/ @see -ftrapv
// Returns -𝑥, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @return rdx:rax is -𝑥
// @see -ftrapv
__negvti2:
mov %rdi,%rax
mov %rsi,%rdx

View file

@ -20,8 +20,8 @@
.privileged
.source __FILE__
/ Arithmetic overflow handler.
/ @see -ftrapv
// Arithmetic overflow handler.
// @see -ftrapv
__on_arithmetic_overflow:
push %rbp
mov %rsp,%rbp

View file

@ -18,10 +18,10 @@
*/
#include "libc/macros.h"
/ Jump table for palignr() with non-constexpr immediate parameter.
/
/ @note needs ssse3 cf. prescott c. 2004 cf. bulldozer c. 2011
/ @see palignr()
// Jump table for palignr() with non-constexpr immediate parameter.
//
// @note needs ssse3 cf. prescott c. 2004 cf. bulldozer c. 2011
// @see palignr()
.align 8
__palignrs:
palignr $0,%xmm1,%xmm0

View file

@ -18,7 +18,7 @@
*/
#include "libc/macros.h"
/ Jump table for pslldq() with non-constexpr immediate parameter.
// Jump table for pslldq() with non-constexpr immediate parameter.
.align 8
__pslldqs:
pslldq $0,%xmm0

View file

@ -18,7 +18,7 @@
*/
#include "libc/macros.h"
/ Jump table for psrldq() with non-constexpr immediate parameter.
// Jump table for psrldq() with non-constexpr immediate parameter.
.align 8
__psrldqs:
psrldq $0,%xmm0

View file

@ -53,11 +53,11 @@ __asan_report_load16:
.endfn __asan_report_load16,globl
__asan_report_load32:
push $32
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_load32,globl
OnReportLoad:
pop %rsi
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn OnReportLoad
__asan_report_load_n:
lea __asan_report_load(%rip),%r11
@ -86,15 +86,15 @@ __asan_report_store16:
.endfn __asan_report_store16,globl
__asan_report_store32:
push $32
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_store32,globl
ReportStore:
pop %rsi
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn ReportStore
__asan_report_store_n:
lea __asan_report_store(%rip),%r11
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_store_n,globl
__asan_report_noreentry:
@ -152,7 +152,7 @@ __asan_stack_free_9:
.endfn __asan_stack_free_9,globl
__asan_stack_free_10:
push $10
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_stack_free_10,globl
OnStackFree:
pop %rdx
@ -201,7 +201,7 @@ __asan_stack_malloc_9:
.endfn __asan_stack_malloc_9,globl
__asan_stack_malloc_10:
push $10
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_stack_malloc_10,globl
OnStackMalloc:
pop %rsi
@ -212,7 +212,7 @@ __asan_version_mismatch_check_v8:
ret
.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
push %rdi
push %rsi

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥-𝑦, aborting on overflow.
/
/ @param rdi is int64 𝑥
/ @param rsi is int64 𝑦
/ @return rax is 𝑥-𝑦
/ @see -ftrapv
// Returns 𝑥-𝑦, aborting on overflow.
//
// @param rdi is int64 𝑥
// @param rsi is int64 𝑦
// @return rax is 𝑥-𝑦
// @see -ftrapv
__subvdi3:
mov %rdi,%rax
sub %rsi,%rax

View file

@ -21,11 +21,11 @@
.privileged
.alignfunc
/ Returns 𝑥-𝑦, aborting on overflow.
/
/ @param edi is int32 𝑥
/ @param esi is int32 𝑦
/ @see -ftrapv
// Returns 𝑥-𝑦, aborting on overflow.
//
// @param edi is int32 𝑥
// @param esi is int32 𝑦
// @see -ftrapv
__subvsi3:
mov %edi,%eax
sub %esi,%eax

View file

@ -21,12 +21,12 @@
.privileged
.alignfunc
/ Returns 𝑥-𝑦, aborting on overflow.
/
/ @param rdi:rsi is int128 𝑥
/ @param rdx:rcx is int128 𝑦
/ @return rdx:rax is 𝑥-𝑦
/ @see -ftrapv
// Returns 𝑥-𝑦, aborting on overflow.
//
// @param rdi:rsi is int128 𝑥
// @param rdx:rcx is int128 𝑦
// @return rdx:rax is 𝑥-𝑦
// @see -ftrapv
__subvti3:
mov %rdi,%rax
sub %rdx,%rax

View file

@ -1,15 +1,18 @@
#ifndef 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
*/
#define kLogFatal 0u
#define kLogError 1u
#define kLogWarn 2u
#define kLogInfo 3u
#define kLogVerbose 4u
#define kLogDebug 5u
#define kLogFatal 0
#define kLogError 1
#define kLogWarn 2
#define kLogInfo 3
#define kLogVerbose 4
#define kLogDebug 5
/**
* Log level for compile-time DCE.
@ -27,10 +30,6 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct sigset;
struct winsize;
typedef struct FILE FILE;
extern FILE *g_logfile;
void perror(const char *) relegated; /* print the last system error */

View file

@ -19,9 +19,9 @@
#include "libc/macros.h"
.source __FILE__
/ These function names make it a bit more obvious which signal
/ caused the crash, particularly in the GDB GUI. They're coded
/ into an array to pinch pennies on code size registering them.
// These function names make it a bit more obvious which signal
// caused the crash, particularly in the GDB GUI. They're coded
// into an array to pinch pennies on code size registering them.
__oncrash_thunks:

View file

@ -49,7 +49,7 @@ __ubsan_handle_type_mismatch_v1_abort:
__ubsan_handle_add_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_add_overflow_abort,globl
__ubsan_handle_add_overflow:
loadstr "add_overflow",si
@ -58,7 +58,7 @@ __ubsan_handle_add_overflow:
__ubsan_handle_alignment_assumption_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_alignment_assumption_abort,globl
__ubsan_handle_alignment_assumption:
loadstr "alignment_assumption",si
@ -67,7 +67,7 @@ __ubsan_handle_alignment_assumption:
__ubsan_handle_builtin_unreachable_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_builtin_unreachable_abort,globl
__ubsan_handle_builtin_unreachable:
loadstr "builtin_unreachable",si
@ -76,7 +76,7 @@ __ubsan_handle_builtin_unreachable:
__ubsan_handle_cfi_bad_type_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_cfi_bad_type_abort,globl
__ubsan_handle_cfi_bad_type:
loadstr "cfi_bad_type",si
@ -85,7 +85,7 @@ __ubsan_handle_cfi_bad_type:
__ubsan_handle_cfi_check_fail_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_cfi_check_fail_abort,globl
__ubsan_handle_cfi_check_fail:
loadstr "cfi_check_fail",si
@ -94,7 +94,7 @@ __ubsan_handle_cfi_check_fail:
__ubsan_handle_divrem_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_divrem_overflow_abort,globl
__ubsan_handle_divrem_overflow:
loadstr "divrem_overflow",si
@ -103,7 +103,7 @@ __ubsan_handle_divrem_overflow:
__ubsan_handle_dynamic_type_cache_miss_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,globl
__ubsan_handle_dynamic_type_cache_miss:
loadstr "dynamic_type_cache_miss",si
@ -112,7 +112,7 @@ __ubsan_handle_dynamic_type_cache_miss:
__ubsan_handle_function_type_mismatch_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_function_type_mismatch_abort,globl
__ubsan_handle_function_type_mismatch:
loadstr "function_type_mismatch",si
@ -121,7 +121,7 @@ __ubsan_handle_function_type_mismatch:
__ubsan_handle_implicit_conversion_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_implicit_conversion_abort,globl
__ubsan_handle_implicit_conversion:
loadstr "implicit_conversion",si
@ -130,7 +130,7 @@ __ubsan_handle_implicit_conversion:
__ubsan_handle_invalid_builtin_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_invalid_builtin_abort,globl
__ubsan_handle_invalid_builtin:
loadstr "invalid_builtin",si
@ -139,7 +139,7 @@ __ubsan_handle_invalid_builtin:
__ubsan_handle_load_invalid_value_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_load_invalid_value_abort,globl
__ubsan_handle_load_invalid_value:
loadstr "load_invalid_value (try checking for uninitialized variables)",si
@ -148,7 +148,7 @@ __ubsan_handle_load_invalid_value:
__ubsan_handle_missing_return_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_missing_return_abort,globl
__ubsan_handle_missing_return:
loadstr "missing_return",si
@ -157,7 +157,7 @@ __ubsan_handle_missing_return:
__ubsan_handle_mul_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_mul_overflow_abort,globl
__ubsan_handle_mul_overflow:
loadstr "mul_overflow",si
@ -166,7 +166,7 @@ __ubsan_handle_mul_overflow:
__ubsan_handle_negate_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_negate_overflow_abort,globl
__ubsan_handle_negate_overflow:
loadstr "negate_overflow",si
@ -175,7 +175,7 @@ __ubsan_handle_negate_overflow:
__ubsan_handle_nonnull_arg_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nonnull_arg_abort,globl
__ubsan_handle_nonnull_arg:
loadstr "nonnull_arg",si
@ -184,7 +184,7 @@ __ubsan_handle_nonnull_arg:
__ubsan_handle_nonnull_return_v1_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
__ubsan_handle_nonnull_return_v1:
loadstr "nonnull_return_v1",si
@ -197,7 +197,7 @@ __ubsan_hop:
__ubsan_handle_nullability_arg_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nullability_arg_abort,globl
__ubsan_handle_nullability_arg:
loadstr "nullability_arg",si
@ -206,7 +206,7 @@ __ubsan_handle_nullability_arg:
__ubsan_handle_nullability_return_v1_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nullability_return_v1_abort,globl
__ubsan_handle_nullability_return_v1:
loadstr "nullability_return_v1",si
@ -215,7 +215,7 @@ __ubsan_handle_nullability_return_v1:
__ubsan_handle_pointer_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_pointer_overflow_abort,globl
__ubsan_handle_pointer_overflow:
loadstr "pointer_overflow",si
@ -224,7 +224,7 @@ __ubsan_handle_pointer_overflow:
__ubsan_handle_shift_out_of_bounds_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_shift_out_of_bounds_abort,globl
__ubsan_handle_shift_out_of_bounds:
loadstr "shift_out_of_bounds",si
@ -233,7 +233,7 @@ __ubsan_handle_shift_out_of_bounds:
__ubsan_handle_sub_overflow_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_sub_overflow_abort,globl
__ubsan_handle_sub_overflow:
loadstr "sub_overflow",si
@ -242,7 +242,7 @@ __ubsan_handle_sub_overflow:
__ubsan_handle_vla_bound_not_positive_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_vla_bound_not_positive_abort,globl
__ubsan_handle_vla_bound_not_positive:
loadstr "vla_bound_not_positive",si
@ -251,7 +251,7 @@ __ubsan_handle_vla_bound_not_positive:
__ubsan_handle_nonnull_return_abort:
nop
/ fallthrough
// fallthrough
.endfn __ubsan_handle_nonnull_return_abort,globl
__ubsan_handle_nonnull_return:
loadstr "nonnull_return",si

View file

@ -20,7 +20,7 @@
.text.unlikely
.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:
loadstr "==",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.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:
loadstr ">=",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.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:
loadstr ">",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.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:
loadstr "<=",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.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:
loadstr "<",dx
jmp __check_fail_ndebug

View file

@ -20,7 +20,7 @@
.text.unlikely
.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:
loadstr "!=",dx
jmp __check_fail_ndebug

View file

@ -23,7 +23,7 @@
#define vzeroupper
#endif
/ Begins definition of frameless function that calls no functions.
// Begins definition of frameless function that calls no functions.
.macro .leafprologue
#if !(defined(TINY) && !defined(__PG__))
push %rbp
@ -31,7 +31,7 @@
#endif
.endm
/ Ends definition of frameless function that calls no functions.
// Ends definition of frameless function that calls no functions.
.macro .leafepilogue
#if !(defined(TINY) && !defined(__PG__))
pop %rbp
@ -39,16 +39,16 @@
ret
.endm
/ Good alignment for functions where alignment actually helps.
/ @note 16-byte
// Good alignment for functions where alignment actually helps.
// @note 16-byte
.macro .alignfunc
#ifndef __OPTIMIZE_SIZE__
.p2align 4
#endif
.endm
/ Good alignment for loops where alignment actually helps.
/ @note 16-byte if <10 padding otherwise 8-byte
// Good alignment for loops where alignment actually helps.
// @note 16-byte if <10 padding otherwise 8-byte
.macro .alignloop
#ifndef __OPTIMIZE_SIZE__
.p2align 4,,10
@ -56,8 +56,8 @@
#endif
.endm
/ Loads Effective Address
/ Supporting security blankets
// Loads Effective Address
// Supporting security blankets
.macro plea symbol:req reg64:req reg32:req
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
lea \symbol(%rip),\reg64
@ -66,8 +66,8 @@
#endif
.endm
/ Loads Effective Address to Stack
/ Supporting security blankets
// Loads Effective Address to Stack
// Supporting security blankets
.macro pshaddr symbol:req
#if __PIC__ + __PIE__ + __code_model_medium__ + __code_model_large__ + 0 > 1
push $IMAGE_BASE_VIRTUAL+RVA(\symbol)(%rip),\reg64
@ -76,12 +76,12 @@
#endif
.endm
/ TODO(jart): delete
/ Loads Effective Address
/ Supporting security blankets
// TODO(jart): delete
// Loads Effective Address
// Supporting security blankets
.macro ezlea symbol:req reg:req
#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
#else
mov $\symbol,%e\reg
@ -97,7 +97,7 @@
#endif
.endm
/ Creates first stack frame.
// Creates first stack frame.
.macro .frame0
and $-16,%rsp
xor %ebp,%ebp
@ -106,38 +106,33 @@
.macro .source symbol:req
.endm
/ Inserts profiling hook in prologue if cc wants it.
/
/ Cosmopolitan does this in a slightly different way from normal
/ GNU toolchains. We always use the -mnop-mcount behavior, since
/ the runtime is able to morph the binary at runtime. It is good
/ since we can put hooks for profiling and function tracing into
/ most builds, without any impact on performance.
/
/ @cost ≥0.3 cycles, 5 bytes
/ @see build/compile
// Inserts profiling hook in prologue if cc wants it.
//
// Cosmopolitan does this in a slightly different way from normal
// GNU toolchains. We always use the -mnop-mcount behavior, since
// the runtime is able to morph the binary at runtime. It is good
// since we can put hooks for profiling and function tracing into
// most builds, without any impact on performance.
//
// @cost ≥0.3 cycles, 5 bytes
// @see build/compile
.macro .profilable
#ifdef __PG__
1382:
#if defined(__MFENTRY__)
call __fentry__
#elif defined(__PIC__) || defined(__PIE__)
/ nopw 0x00(%rax,%rax,1)
// nopw 0x00(%rax,%rax,1)
.byte 0x66,0x0f,0x1f,0x44,0x00,0x00
#else
/ nopl 0x00(%rax,%rax,1)
// nopl 0x00(%rax,%rax,1)
.byte 0x0f,0x1f,0x44,0x00,0x00
#endif
#if defined(__MRECORD_MCOUNT__) && !defined(__MFENTRY__)
.section __mcount_loc,"a",@progbits
.quad 1382b
.previous
#endif
#endif
.endm
/ Pushes RVA on stack of linktime mergeable string literal.
/ @see popstr
// Pushes RVA on stack of linktime mergeable string literal.
// @see popstr
.macro pushstr text
.section .rodata.str1.1,"aSM",@progbits,1
.Lstr\@: .asciz "\text"
@ -146,14 +141,14 @@
push $.Lstr\@ - IMAGE_BASE_VIRTUAL
.endm
/ Pops off stack string address.
/ @see pushstr
// Pops off stack string address.
// @see pushstr
.macro popstr dest:req
addl $IMAGE_BASE_VIRTUAL,(%rsp)
pop \dest
.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
.section .rodata.str1.1,"aSM",@progbits,1
.type .Lstr\@,@object
@ -175,8 +170,8 @@
.endif
.endm
/ TODO(jart): delete
/ Loads address of linktime mergeable string literal into register.
// TODO(jart): delete
// Loads address of linktime mergeable string literal into register.
.macro loadstr text:req reg:req regsz bias=0
.section .rodata.str1.1,"aSM",@progbits,1
.type .Lstr\@,@object

View file

@ -14,7 +14,6 @@
#define FALSE 0
#define alignas(x) _Alignas(x)
#define static_assert(x) _Static_assert(x, #x)
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
#define ROUNDDOWN(X, K) ((X) & -(K))

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
╚─────────────────────────────────────────────────────────────────────────────*/
/ Shorthand notation for widely-acknowledged sections.
// Shorthand notation for widely-acknowledged sections.
.macro .rodata
.section .rodata,"a",@progbits
.endm
@ -62,11 +62,11 @@
.section .text.windows,"ax",@progbits
.endm
/ Mergeable numeric constant sections.
/
/ @note linker de-dupes item/values across whole compile
/ @note therefore item/values are reordered w.r.t. link order
/ @note therefore no section relative addressing
// Mergeable numeric constant sections.
//
// @note linker de-dupes item/values across whole compile
// @note therefore item/values are reordered w.r.t. link order
// @note therefore no section relative addressing
.macro .rodata.cst4
.section .rodata.cst4,"aM",@progbits,4
.align 4
@ -96,33 +96,33 @@
.align 4
.endm
/ Mergeable NUL-terminated UTF-8 string constant section.
/
/ @note linker de-dupes C strings here across whole compile
/ @note therefore item/values are reordered w.r.t. link order
/ @note therefore no section relative addressing
// Mergeable NUL-terminated UTF-8 string constant section.
//
// @note linker de-dupes C strings here across whole compile
// @note therefore item/values are reordered w.r.t. link order
// @note therefore no section relative addressing
.macro .rodata.str1.1
.section .rodata.str1.1,"aSM",@progbits,1
.align 1
.endm
/ Locates unreferenced code invulnerable to --gc-sections.
// Locates unreferenced code invulnerable to --gc-sections.
.macro .keep.text
.section .keep.text,"ax",@progbits
.endm
/ Flags code as only allowed for testing purposes.
// Flags code as only allowed for testing purposes.
.macro .testonly
.section .test,"ax",@progbits
.endm
/ Makes code runnable while code morphing.
// Makes code runnable while code morphing.
.macro .privileged
.section .privileged,"ax",@progbits
.endm
/ Post-Initialization Read-Only (PIRO) BSS section.
/ @param ss is an optional string, for control image locality
// Post-Initialization Read-Only (PIRO) BSS section.
// @param ss is an optional string, for control image locality
.macro .piro ss
.ifnb \ss
.section .piro.sort.bss.\ss,"aw",@nobits
@ -131,9 +131,9 @@
.endif
.endm
/ Helpers for Cosmopolitan _init() amalgamation magic.
/ @param name should be consistent across macros for a module
/ @see libc/runtime/_init.S
// Helpers for Cosmopolitan _init() amalgamation magic.
// @param name should be consistent across macros for a module
// @see libc/runtime/_init.S
.macro .initro number:req name:req
.section .initro.\number\().\name,"a",@progbits
.align 8
@ -151,16 +151,16 @@
.previous
.endm
/ Declares alternative implementation of function.
/ @param implement e.g. tinymath_pow
/ @param canonical e.g. pow
// Declares alternative implementation of function.
// @param implement e.g. tinymath_pow
// @param canonical e.g. pow
.macro .alias implement:req canonical:req
.equ \canonical,\implement
.weak \canonical
.endm
/ Ends function definition.
/ @cost saves 1-3 lines of code
// Ends function definition.
// @cost saves 1-3 lines of code
.macro .endfn name:req bnd vis
.size \name,.-\name
.type \name,@function
@ -172,8 +172,8 @@
.endif
.endm
/ Ends variable definition.
/ @cost saves 1-3 lines of code
// Ends variable definition.
// @cost saves 1-3 lines of code
.macro .endobj name:req bnd vis
.size \name,.-\name
.type \name,@object
@ -185,35 +185,35 @@
.endif
.endm
/ LOOP Instruction Replacement.
/ With its mop-Fusion Mexican equivalent.
/ Thus avoiding 3x legacy pipeline slowdown.
// LOOP Instruction Replacement.
// With its mop-Fusion Mexican equivalent.
// Thus avoiding 3x legacy pipeline slowdown.
.macro .loop label:req
.byte 0x83,0xe9,0x01 # sub $1,%ecx
jnz \label
.endm
/ Pushes CONSTEXPR [-128,127].
/ @note assembler is wrong for non-literal constexprs
// Pushes CONSTEXPR ∈ [-128,127].
// @note assembler is wrong for non-literal constexprs
.macro pushb x:req
.byte 0x6a,\x
.endm
/ Sign-extends CONSTEXPR [-128,127] to REGISTER.
/ @cost ≥1 cycles, -2 bytes
// Sign-extends CONSTEXPR ∈ [-128,127] to REGISTER.
// @cost ≥1 cycles, -2 bytes
.macro pushpop constexpr:req register:req
pushb \constexpr
pop \register
.endm
/ Moves REGISTER to REGISTER.
/ @cost ≥1 cycles, -1 REX byte
// Moves REGISTER to REGISTER.
// @cost ≥1 cycles, -1 REX byte
.macro movpp src:req dest:req
push \src
pop \dest
.endm
/ Declares optional function.
// Declares optional function.
.macro .optfn fn:req
.globl \fn
.weak \fn
@ -221,8 +221,8 @@
.type \fn,@function
.endm
/ Embeds fixed-width zero-filled string table.
/ @note zero-padded nul-terminated
// Embeds fixed-width zero-filled string table.
// @note zero-padded ≠ nul-terminated
.macro .fxstr width head rest:vararg
.ifnb \head
0: .ascii "\head"
@ -231,15 +231,15 @@
.endif
.endm
/ Embeds Fixed-Width Zero-Padded String.
/ @note .fxstr is better
// Embeds Fixed-Width Zero-Padded String.
// @note .fxstr is better
.macro .ascin str:req fieldsize:req
1347: .ascii "\str"
.org 1347b+\fieldsize,0x00
.endm
/ Marks symbols as object en-masse.
/ @note zero-padded nul-terminated
// Marks symbols as object en-masse.
// @note zero-padded ≠ nul-terminated
.macro .object symbol rest:vararg
.ifnb \symbol
.type \symbol,@object
@ -247,18 +247,14 @@
.endif
.endm
/ Pads function prologue unconditionally for runtime hooking.
/ @cost ≥0.3 cycles, 5 bytes
/ @see .profilable
// Pads function prologue unconditionally for runtime hooking.
// @cost ≥0.3 cycles, 5 bytes
// @see .profilable
.macro .hookable
/ nopl 0x00(%rax,%rax,1)
83457: .byte 0x0f,0x1f,0x44,0x00,0x00
.section __mcount_loc,"a",@progbits
.quad 83457b
.previous
.byte 0x0f,0x1f,0x44,0x00,0x00
.endm
/ Puts initialized data in uninitialized data section.
// Puts initialized data in uninitialized data section.
.macro .bsdata name:req expr:req bnd vis
.section .initbss.300._init_\name,"aw",@nobits
\name: .quad 0
@ -274,9 +270,9 @@ _init_\name:
.previous
.endm
/ ICE Breakpoint.
/ Modern gas forgot this but objdump knows
/ @mode long,legacy,real
// ICE Breakpoint.
// Modern gas forgot this but objdump knows
// @mode long,legacy,real
.macro icebp
.byte 0xF1
.endm
@ -284,8 +280,8 @@ _init_\name:
icebp
.endm
/ Sets breakpoint for software debugger.
/ @mode long,legacy,real
// Sets breakpoint for software debugger.
// @mode long,legacy,real
.macro .softicebp
.byte 0x53 # push bx
.byte 0x87,0xdb # xchg bx,bx (bochs breakpoint)
@ -294,38 +290,38 @@ _init_\name:
int3 # gdb breakpoint
.endm
/ Assembles Intel Official 4-Byte NOP.
// Assembles Intel Official 4-Byte NOP.
.macro fatnop4
.byte 0x0f,0x1f,0x40,0x00
.endm
/ Pulls unrelated module into linkage.
/
/ In order for this technique to work with --gc-sections, another
/ module somewhere might want to weakly reference whats yoinked.
// Pulls unrelated module into linkage.
//
// In order for this technique to work with --gc-sections, another
// module somewhere might want to weakly reference whats yoinked.
.macro yoink symbol:req
.section .yoink
nop "\symbol"
nopl "\symbol"(%rip)
.previous
.endm
.macro .yoink symbol:req
.section .yoink
nop "\symbol"
nopl "\symbol"(%rip)
.previous
.endm
/ Calls Windows function.
/
/ @param cx,dx,r8,r9,stack
/ @return ax
/ @clob ax,cx,dx,r8-r11
// Calls Windows function.
//
// @param cx,dx,r8,r9,stack
// @return ax
// @clob ax,cx,dx,r8-r11
.macro ntcall symbol:req
sub $32,%rsp
call *\symbol(%rip)
add $32,%rsp
.endm
/ Custom emulator instruction for bottom stack frame.
// Custom emulator instruction for bottom stack frame.
.macro bofram endfunc:req
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
.endm

View file

@ -20,12 +20,12 @@
#include "libc/notice.inc"
.source __FILE__
/ Allocates n * itemsize bytes, initialized to zero.
/
/ @param rdi is number of items (n)
/ @param rsi is size of each item (itemsize)
/ @return rax is memory address, or NULL w/ errno
/ @note overreliance on memalign is a sure way to fragment space
/ @see dlcalloc()
// Allocates n * itemsize bytes, initialized to zero.
//
// @param rdi is number of items (n)
// @param rsi is size of each item (itemsize)
// @return rax is memory address, or NULL w/ errno
// @note overreliance on memalign is a sure way to fragment space
// @see dlcalloc()
calloc: jmp *hook_calloc(%rip)
.endfn calloc,globl

View file

@ -19,67 +19,67 @@
#include "libc/macros.h"
.source __FILE__
/ Frees memory the C++ way.
/
/ \param %rdi is pointer, or NULL for no-op
/ \param %rsi is ignored
/ \param %rdx is ignored
// Frees memory the C++ way.
//
// \param %rdi is pointer, or NULL for no-op
// \param %rsi is ignored
// \param %rdx is ignored
_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
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
_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
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
_ZdlPvRKSt9nothrow_t:
/ operator delete(void*, std::nothrow_t const&)
// operator delete(void*, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvRKSt9nothrow_t,weak
_ZdaPvRKSt9nothrow_t:
/ operator delete[](void*, std::nothrow_t const&)
// operator delete[](void*, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvRKSt9nothrow_t,weak
_ZdlPvmSt11align_val_t:
/ operator delete(void*, unsigned long, std::align_val_t)
// operator delete(void*, unsigned long, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvmSt11align_val_t,weak
_ZdaPvmSt11align_val_t:
/ operator delete[](void*, unsigned long, std::align_val_t)
// operator delete[](void*, unsigned long, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvmSt11align_val_t,weak
_ZdlPvSt11align_val_t:
/ operator delete(void*, std::align_val_t)
// operator delete(void*, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_t,weak
_ZdaPvSt11align_val_t:
/ operator delete[](void*, std::align_val_t)
// operator delete[](void*, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvSt11align_val_t,weak
_ZdaPvm:
/ operator delete[](void*, unsigned long):
// operator delete[](void*, unsigned long):
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvm,weak
_ZdlPvm:
/ operator delete(void*, unsigned long)
// operator delete(void*, unsigned long)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvm,weak
_ZdaPv:
/ operator delete[](void*)
// operator delete[](void*)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPv,weak
_ZdlPv:
/ operator delete(void*)
// operator delete(void*)
jmp *hook_free(%rip)
.endfn _ZdlPv,weak

View file

@ -19,28 +19,28 @@
#include "libc/macros.h"
.source __FILE__
/ Allocates memory the C++ way.
/
/ \param %rdi is bytes to allocate
/ \param %rsi is ignored
/ \return new memory or NULL on OOM
// Allocates memory the C++ way.
//
// \param %rdi is bytes to allocate
// \param %rsi is ignored
// \return new memory or NULL on OOM
_ZnamRKSt9nothrow_t:
/ operator new[](unsigned long, std::nothrow_t const&)
// operator new[](unsigned long, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnamRKSt9nothrow_t,weak
_ZnwmRKSt9nothrow_t:
/ operator new(unsigned long, std::nothrow_t const&)
// operator new(unsigned long, std::nothrow_t const&)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmRKSt9nothrow_t,weak
_Znam:
/ operator new[](unsigned long)
// operator new[](unsigned long)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _Znam,weak
_Znwm:
/ operator new(unsigned long)
// operator new(unsigned long)
test %rdi,%rdi
jne 1f
mov $1,%edi

View file

@ -19,29 +19,29 @@
#include "libc/macros.h"
.source __FILE__
/ Allocates aligned memory the C++ way.
/
/ \param %rdi is bytes to allocate
/ \param %rsi is byte alignment
/ \param %rdx is ignored
/ \return new memory or NULL on OOM
// Allocates aligned memory the C++ way.
//
// \param %rdi is bytes to allocate
// \param %rsi is byte alignment
// \param %rdx is ignored
// \return new memory or NULL on OOM
_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
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
_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
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
_ZnwmSt11align_val_t:
/ operator new(unsigned long, std::align_val_t)
// operator new(unsigned long, std::align_val_t)
nop
/ 𝑠𝑙𝑖𝑑𝑒
// 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmSt11align_val_t,weak
_ZnamSt11align_val_t:
/ operator new[](unsigned long, std::align_val_t)
// operator new[](unsigned long, std::align_val_t)
test %rdi,%rdi
jnz 1f
mov $1,%eax

View file

@ -16,9 +16,8 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/arraylist.internal.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/likely.h"
#include "libc/calls/calls.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/gc.internal.h"
@ -41,22 +40,26 @@ forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
* @return arg
*/
void __defer(struct StackFrame *frame, void *fn, void *arg) {
struct StackFrame *frame2;
/*
* To avoid an API requiring dlmalloc dependency, say:
* defer(free_s, &ptr_not_owned_by_current_frame)
* Rather than:
* defer(weak(free), ptr)
*/
size_t n2;
struct Garbage *p2;
struct StackFrame *f2;
if (!arg) return;
frame2 = __builtin_frame_address(0);
assert(frame2->next == frame);
assert(PointerNotOwnedByParentStackFrame(frame2, frame, arg));
if (append(&__garbage,
(&(const struct Garbage){frame->next, (intptr_t)fn, (intptr_t)arg,
frame->addr})) != -1) {
atomic_store(&frame->addr, (intptr_t)&__gc);
} else {
abort();
f2 = __builtin_frame_address(0);
assert(__garbage.n);
assert(f2->next == frame);
assert(PointerNotOwnedByParentStackFrame(f2, frame, arg));
if (UNLIKELY(__garbage.i == __garbage.n)) {
n2 = __garbage.n + (__garbage.n >> 1);
p2 = malloc(n2 * sizeof(*__garbage.p));
memcpy(p2, __garbage.p, __garbage.n * sizeof(*__garbage.p));
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;
}

View file

@ -19,15 +19,15 @@
#include "libc/macros.h"
.source __FILE__
/ Free memory returned by malloc() & co.
/
/ Releases the chunk of memory pointed to by p, that had been
/ 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
/ already freed, free(p) will by default cuase the current program to
/ abort.
/
/ @param rdi is allocation address, which may be NULL
/ @see dlfree()
// Free memory returned by malloc() & co.
//
// Releases the chunk of memory pointed to by p, that had been
// 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
// already freed, free(p) will by default cuase the current program to
// abort.
//
// @param rdi is allocation address, which may be NULL
// @see dlfree()
free: jmp *hook_free(%rip)
.endfn free,globl

Some files were not shown because too many files have changed in this diff Show more