mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
ff77f2a6af
- This change fixes a bug that allowed unbuffered printf() output (to streams like stderr) to be truncated. This regression was introduced some time between now and the last release. - POSIX specifies all functions as thread safe by default. This change works towards cleaning up our use of the @threadsafe / @threadunsafe documentation annotations to reflect that. The goal is (1) to use @threadunsafe to document functions which POSIX say needn't be thread safe, and (2) use @threadsafe to document functions that we chose to implement as thread safe even though POSIX didn't mandate it. - Tidy up the clock_gettime() implementation. We're now trying out a cleaner approach to system call support that aims to maintain the Linux errno convention as long as possible. This also fixes bugs that existed previously, where the vDSO errno wasn't being translated properly. The gettimeofday() system call is now a wrapper for clock_gettime(), which reduces bloat in apps that use both. - The recently-introduced improvements to the execute bit on Windows has had bugs fixed. access(X_OK) on a directory on Windows now succeeds. fstat() will now perform the MZ/#! ReadFile() operation correctly. - Windows.h is no longer included in libc/isystem/, because it confused PCRE's build system into thinking Cosmopolitan is a WIN32 platform. Cosmo's Windows.h polyfill was never even really that good, since it only defines a subset of the subset of WIN32 APIs that Cosmo defines. - The setlongerjmp() / longerjmp() APIs are removed. While they're nice APIs that are superior to the standardized setjmp / longjmp functions, they weren't superior enough to not be dead code in the monorepo. If you use these APIs, please file an issue and they'll be restored. - The .com appending magic has now been removed from APE Loader.
528 lines
12 KiB
C
528 lines
12 KiB
C
#ifndef COSMOPOLITAN_LIBC_MACROS_H_
|
|
#define COSMOPOLITAN_LIBC_MACROS_H_
|
|
#if 0
|
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
|
│ cosmopolitan § macros ─╬─│┼
|
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
|
#endif
|
|
|
|
/**
|
|
* @fileoverview Common C preprocessor, assembler, and linker macros.
|
|
*/
|
|
|
|
#ifdef MAX
|
|
#undef MAX
|
|
#endif
|
|
|
|
#ifdef MIN
|
|
#undef MIN
|
|
#endif
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
#define IS2POW(X) (!((X) & ((X)-1)))
|
|
#define ROUNDUP(X, K) (((X) + (K)-1) & -(K))
|
|
#define ROUNDDOWN(X, K) ((X) & -(K))
|
|
#ifndef __ASSEMBLER__
|
|
#define ABS(X) ((X) >= 0 ? (X) : -(X))
|
|
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
|
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
|
#else
|
|
// The GNU assembler does not grok the ?: ternary operator; furthermore,
|
|
// boolean expressions yield -1 and 0 for "true" and "false", not 1 and 0.
|
|
#define __MAPBOOL(P) (!!(P) / (!!(P) + !(P)))
|
|
#define __IFELSE(P, X, Y) (__MAPBOOL(P) * (X) + __MAPBOOL(!(P)) * (Y))
|
|
#define MIN(X, Y) (__IFELSE((Y) > (X), (X), (Y)))
|
|
#define MAX(X, Y) (__IFELSE((Y) < (X), (X), (Y)))
|
|
#endif
|
|
#define PASTE(A, B) __PASTE(A, B)
|
|
#define STRINGIFY(A) __STRINGIFY(A)
|
|
#define EQUIVALENT(X, Y) (__builtin_constant_p((X) == (Y)) && ((X) == (Y)))
|
|
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
|
|
#define TYPE_SIGNED(type) (((type)-1) < 0)
|
|
#define TYPE_INTEGRAL(type) (((type)0.5) != 0.5)
|
|
|
|
#define ARRAYLEN(A) \
|
|
((sizeof(A) / sizeof(*(A))) / ((unsigned)!(sizeof(A) % sizeof(*(A)))))
|
|
|
|
#define __STRINGIFY(A) #A
|
|
#define __PASTE(A, B) A##B
|
|
#ifdef __ASSEMBLER__
|
|
// clang-format off
|
|
|
|
// Ends function definition.
|
|
// @cost saves 1-3 lines of code
|
|
.macro .endfn name:req bnd vis
|
|
.size "\name",.-"\name"
|
|
.type "\name",@function
|
|
.ifnb \bnd
|
|
.\bnd "\name"
|
|
.endif
|
|
.ifnb \vis
|
|
.\vis "\name"
|
|
.endif
|
|
.endm
|
|
|
|
// Ends variable definition.
|
|
// @cost saves 1-3 lines of code
|
|
.macro .endobj name:req bnd vis
|
|
.size "\name",.-"\name"
|
|
.type "\name",@object
|
|
.ifnb \bnd
|
|
.\bnd "\name"
|
|
.endif
|
|
.ifnb \vis
|
|
.\vis "\name"
|
|
.endif
|
|
.endm
|
|
|
|
// Shorthand notation for widely-acknowledged sections.
|
|
.macro .rodata
|
|
.section .rodata,"a",@progbits
|
|
.endm
|
|
.macro .init
|
|
.section .init,"ax",@progbits
|
|
.endm
|
|
.macro .real
|
|
.section .text.real,"ax",@progbits
|
|
.endm
|
|
.macro .head
|
|
.section .text.head,"ax",@progbits
|
|
.endm
|
|
.macro .text.startup
|
|
.section .text.startup,"ax",@progbits
|
|
.endm
|
|
.macro .text.exit
|
|
.section .text.exit,"ax",@progbits
|
|
.endm
|
|
.macro .firstclass
|
|
.section .text.hot,"ax",@progbits
|
|
.endm
|
|
.macro .text.unlikely
|
|
.section .text.unlikely,"ax",@progbits
|
|
.endm
|
|
.macro .text.likely
|
|
.section .text.hot,"ax",@progbits
|
|
.endm
|
|
.macro .text.modernity
|
|
.section .text.modernity,"ax",@progbits
|
|
.balign 16
|
|
.endm
|
|
.macro .text.antiquity
|
|
.section .text.antiquity,"ax",@progbits
|
|
.endm
|
|
.macro .text.hot
|
|
.section .text.hot,"ax",@progbits
|
|
.endm
|
|
.macro .preinit_array
|
|
.section .preinit_array,"a",@init_array
|
|
.endm
|
|
.macro .init_array
|
|
.section .init_array,"a",@init_array
|
|
.endm
|
|
.macro .text.windows
|
|
.section .text.windows,"ax",@progbits
|
|
.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
|
|
.macro .rodata.str1.1
|
|
.section .rodata.str1.1,"aMS",@progbits,1
|
|
.balign 1
|
|
.endm
|
|
|
|
// Locates unreferenced code invulnerable to --gc-sections.
|
|
.macro .keep.text
|
|
.section .keep.text,"ax",@progbits
|
|
.endm
|
|
|
|
// Flags code as only allowed for testing purposes.
|
|
.macro .testonly
|
|
.section .test,"ax",@progbits
|
|
.endm
|
|
|
|
// Makes code runnable while code morphing.
|
|
.macro .privileged
|
|
.section .privileged,"ax",@progbits
|
|
.endm
|
|
|
|
// 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
|
|
|
|
#ifdef __aarch64__
|
|
.macro jmp dest:req
|
|
b \dest
|
|
.endm
|
|
#endif
|
|
|
|
// 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
|
|
#ifdef __x86_64__
|
|
nopl "\symbol"(%rip)
|
|
#elif defined(__aarch64__)
|
|
b "\symbol"
|
|
#endif
|
|
.previous
|
|
.endm
|
|
|
|
// Begins definition of frameless function that calls no functions.
|
|
.macro .leafprologue
|
|
#if !(defined(TINY) && !defined(__PG__))
|
|
#ifdef __x86_64__
|
|
push %rbp
|
|
mov %rsp,%rbp
|
|
#elif defined(__aarch64__)
|
|
stp x29,x30,[sp,#-16]!
|
|
mov x29,sp
|
|
#endif
|
|
#endif
|
|
.endm
|
|
|
|
// Ends definition of frameless function that calls no functions.
|
|
.macro .leafepilogue
|
|
#if !(defined(TINY) && !defined(__PG__))
|
|
#ifdef __x86_64__
|
|
pop %rbp
|
|
#elif defined(__aarch64__)
|
|
ldp x29,x30,[sp],#16
|
|
#endif
|
|
#endif
|
|
ret
|
|
.endm
|
|
|
|
// Documents unreachable assembly code.
|
|
.macro .unreachable
|
|
#if !defined(NDEBUG) && defined(__x86_64__)
|
|
ud2 // crash if contract is broken
|
|
#elif !defined(NDEBUG) && defined(__aarch64__)
|
|
brk #1000
|
|
#elif defined(__FNO_OMIT_FRAME_POINTER__) && defined(__x86_64__)
|
|
nop // avoid noreturn tail call backtrace ambiguity
|
|
#endif
|
|
.endm
|
|
|
|
// Embeds Fixed-Width Zero-Padded String.
|
|
// @note .fxstr is better
|
|
.macro .ascin str:req fieldsize:req
|
|
1347: .ascii "\str"
|
|
.org 1347b+\fieldsize,0x00
|
|
.endm
|
|
|
|
// Inserts --ftrace pre-prologue.
|
|
// This goes immediately before the function symbol.
|
|
// @see .ftrace2
|
|
.macro .ftrace1
|
|
#ifdef FTRACE
|
|
#ifdef __x86_64__
|
|
.rept 9
|
|
nop
|
|
.endr
|
|
#elif defined(__aarch64__)
|
|
.rept 6
|
|
nop
|
|
.endr
|
|
#endif /* __x86_64__ */
|
|
#endif /* FTRACE */
|
|
.endm
|
|
|
|
// Inserts --ftrace prologue.
|
|
// This goes immediately after the function symbol.
|
|
// @see .ftrace1
|
|
.macro .ftrace2
|
|
#ifdef FTRACE
|
|
#ifdef __x86_64__
|
|
xchg %ax,%ax
|
|
#elif defined(__aarch64__)
|
|
nop
|
|
#endif /* __x86_64__ */
|
|
#endif /* FTRACE */
|
|
.endm
|
|
|
|
#ifdef __x86_64__
|
|
|
|
#if __MNO_VZEROUPPER__ + 0
|
|
#define vzeroupper
|
|
#endif
|
|
|
|
// 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
|
|
.balign 4
|
|
.endm
|
|
.macro .rodata.cst8
|
|
.section .rodata.cst8,"aM",@progbits,8
|
|
.balign 8
|
|
.endm
|
|
.macro .rodata.cst16
|
|
.section .rodata.cst16,"aM",@progbits,16
|
|
.balign 16
|
|
.endm
|
|
.macro .rodata.cst32
|
|
.section .rodata.cst32,"aM",@progbits,32
|
|
.balign 32
|
|
.endm
|
|
.macro .rodata.cst64
|
|
.section .rodata.cst64,"aM",@progbits,64
|
|
.balign 64
|
|
.endm
|
|
.macro .tdata
|
|
.section .tdata,"awT",@progbits
|
|
.balign 4
|
|
.endm
|
|
.macro .tbss
|
|
.section .tdata,"awT",@nobits
|
|
.balign 4
|
|
.endm
|
|
|
|
// Loads address of errno into %rcx
|
|
.macro .errno
|
|
call __errno_location
|
|
.endm
|
|
|
|
// 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
|
|
.else
|
|
.section .piro.bss,"aw",@nobits
|
|
.endif
|
|
.endm
|
|
|
|
// 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
|
|
.balign 8
|
|
.endm
|
|
.macro .initbss number:req name:req
|
|
.section ".piro.bss.init.2.\number\().\name","aw",@nobits
|
|
.balign 8
|
|
.endm
|
|
.macro .init.start number:req name:req
|
|
.section ".init.\number\().\name","ax",@progbits
|
|
"\name":
|
|
.endm
|
|
.macro .init.end number:req name:req bnd=globl vis
|
|
.endfn "\name",\bnd,\vis
|
|
.previous
|
|
.endm
|
|
|
|
// LOOP Instruction Replacement.
|
|
.macro .loop label:req
|
|
.byte 0x83
|
|
.byte 0xe9
|
|
.byte 0x01
|
|
jnz \label
|
|
.endm
|
|
|
|
// Pushes CONSTEXPR ∈ [-128,127].
|
|
// @note assembler is wrong for non-literal constexprs
|
|
.macro pushb x:req
|
|
.byte 0x6a
|
|
.byte \x
|
|
.endm
|
|
|
|
// 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
|
|
.macro movpp src:req dest:req
|
|
push \src
|
|
pop \dest
|
|
.endm
|
|
|
|
// Embeds fixed-width zero-filled string table.
|
|
// @note zero-padded ≠ nul-terminated
|
|
.macro .fxstr width head rest:vararg
|
|
.ifnb \head
|
|
0: .ascii "\head"
|
|
.org 0b+\width
|
|
.fxstr \width,\rest
|
|
.endif
|
|
.endm
|
|
|
|
// Marks symbols as object en-masse.
|
|
// @note zero-padded ≠ nul-terminated
|
|
.macro .object symbol rest:vararg
|
|
.ifnb \symbol
|
|
.type \symbol,@object
|
|
.object \rest
|
|
.endif
|
|
.endm
|
|
|
|
// Pads function prologue unconditionally for runtime hooking.
|
|
// @cost ≥0.3 cycles, 5 bytes
|
|
// @see .ftrace1
|
|
.macro .hookable
|
|
.byte 0x0f
|
|
.byte 0x1f
|
|
.byte 0x44
|
|
.byte 0x00
|
|
.byte 0x00
|
|
.endm
|
|
|
|
// 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
|
|
.endobj "\name",\bnd,\vis
|
|
.previous
|
|
.section ".initro.300._init_\name","a",@progbits
|
|
.quad \expr
|
|
.previous
|
|
.section ".init.300._init_\name","ax",@progbits
|
|
"_init_\name":
|
|
movsq
|
|
.endfn "_init_\name"
|
|
.previous
|
|
.endm
|
|
|
|
// ICE Breakpoint.
|
|
// Modern gas forgot this but objdump knows
|
|
// @mode long,legacy,real
|
|
.macro icebp
|
|
.byte 0xF1
|
|
.endm
|
|
.macro int1
|
|
icebp
|
|
.endm
|
|
|
|
// Sets breakpoint for software debugger.
|
|
// @mode long,legacy,real
|
|
.macro .softicebp
|
|
.byte 0x53 # push bx
|
|
.byte 0x87 # xchg bx,bx (bochs breakpoint)
|
|
.byte 0xdb
|
|
.byte 0x5b # pop bx
|
|
.byte 0x66 # xchg ax,ax (microsoft breakpoint)
|
|
.byte 0x90
|
|
int3 # gdb breakpoint
|
|
.endm
|
|
|
|
// Assembles Intel Official 4-Byte NOP.
|
|
.macro fatnop4
|
|
.byte 0x0f,0x1f,0x40,0x00
|
|
.endm
|
|
|
|
// 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.
|
|
.macro bofram endfunc:req
|
|
.byte 0x0f,0x1f,0105,\endfunc-. # nopl disp8(%rbp)
|
|
.endm
|
|
|
|
// Good alignment for functions where alignment actually helps.
|
|
// @note 16-byte
|
|
.macro .alignfunc
|
|
#ifndef __OPTIMIZE_SIZE__
|
|
.p2align 4
|
|
#endif
|
|
.endm
|
|
|
|
// 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
|
|
mov $\symbol,%e\reg
|
|
#else
|
|
mov $\symbol,%e\reg
|
|
#endif
|
|
.endm
|
|
|
|
// 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
|
|
.Lstr\@: .asciz "\text"
|
|
.Lstr\@.size = .-.Lstr\@ - 1
|
|
.size .Lstr\@,.-.Lstr\@
|
|
.previous
|
|
ezlea .Lstr\@,\reg
|
|
.ifnb \regsz
|
|
#ifdef __OPTIMIZE_SIZE__
|
|
.if .Lstr\@.size + \bias < 128
|
|
pushpop .Lstr\@.size,%r\regsz
|
|
.else
|
|
mov $.Lstr\@.size,%e\regsz
|
|
.endif
|
|
#else
|
|
mov $.Lstr\@.size,%e\regsz
|
|
#endif
|
|
.endif
|
|
.endm
|
|
|
|
.macro .poison name:req kind:req
|
|
#ifdef __SANITIZE_ADDRESS__
|
|
2323: .quad 0
|
|
.init.start 304,"_init_\name\()_poison_\@"
|
|
push %rdi
|
|
push %rsi
|
|
ezlea 2323b,di
|
|
mov $8,%esi
|
|
mov $\kind,%edx
|
|
call __asan_poison
|
|
pop %rsi
|
|
pop %rdi
|
|
.init.end 304,"_init_\name\()_poison_\@"
|
|
#endif
|
|
.endm
|
|
|
|
.macro .underrun
|
|
#ifdef __SANITIZE_ADDRESS__
|
|
.poison __BASE_FILE__, -20 # kAsanGlobalUnderrun
|
|
#endif
|
|
.endm
|
|
|
|
.macro .overrun
|
|
#ifdef __SANITIZE_ADDRESS__
|
|
.poison __BASE_FILE__, -21 # kAsanGlobalOverrun
|
|
#endif
|
|
.endm
|
|
|
|
#else
|
|
|
|
.macro .underrun
|
|
.endm
|
|
.macro .overrun
|
|
.endm
|
|
|
|
// clang-format on
|
|
#endif /* __x86_64__ */
|
|
#endif /* __ASSEMBLER__ */
|
|
#endif /* COSMOPOLITAN_LIBC_MACROS_H_ */
|