cosmopolitan/libc/macros.inc
Justine Tunney f4f4caab0e Add x86_64-linux-gnu emulator
I wanted a tiny scriptable meltdown proof way to run userspace programs
and visualize how program execution impacts memory. It helps to explain
how things like Actually Portable Executable works. It can show you how
the GCC generated code is going about manipulating matrices and more. I
didn't feel fully comfortable with Qemu and Bochs because I'm not smart
enough to understand them. I wanted something like gVisor but with much
stronger levels of assurances. I wanted a single binary that'll run, on
all major operating systems with an embedded GPL barrier ZIP filesystem
that is tiny enough to transpile to JavaScript and run in browsers too.

https://justine.storage.googleapis.com/emulator625.mp4
2020-08-25 04:43:42 -07:00

332 lines
8.5 KiB
PHP

/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
│ This program is free software; you can redistribute it and/or modify │
│ it under the terms of the GNU General Public License as published by │
│ the Free Software Foundation; version 2 of the License. │
│ │
│ This program is distributed in the hope that it will be useful, but │
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
│ General Public License for more details. │
│ │
│ You should have received a copy of the GNU General Public License │
│ along with this program; if not, write to the Free Software │
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
│ 02110-1301 USA │
╚─────────────────────────────────────────────────────────────────────────────*/
/ 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 .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
.align 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 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
.endm
.macro .rodata.cst8
.section .rodata.cst8,"aM",@progbits,8
.align 8
.endm
.macro .rodata.cst16
.section .rodata.cst16,"aM",@progbits,16
.align 16
.endm
.macro .rodata.cst32
.section .rodata.cst32,"aM",@progbits,32
.align 32
.endm
.macro .rodata.cst64
.section .rodata.cst64,"aM",@progbits,64
.align 64
.endm
.macro .tdata
.section .tdata,"awT",@progbits
.align 4
.endm
.macro .tbss
.section .tdata,"awT",@nobits
.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
.macro .rodata.str1.1
.section .rodata.str1.1,"aSM",@progbits,1
.align 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
/ 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
.align 8
.endm
.macro .initbss number:req name:req
.section .piro.bss.init.2.\number\().\name,"aw",@nobits
.align 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
/ 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
.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
/ Custom emulator instruction for bottom stack frame.
.macro bofram endfunc:req
.byte 0x0f,0x1f,0x45,\endfunc-. # nopl disp8(%rbp)
.endm
/ Overrides LOOP instruction.
/ 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
.macro pushb x:req
.byte 0x6a,\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
/ Declares optional function.
.macro .optfn fn:req
.globl \fn
.weak \fn
.equ \fn,missingno
.type \fn,@function
.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
/ 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
.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 .profilable
.macro .hookable
/ nopl 0x00(%rax,%rax,1)
83457: .byte 0x0f,0x1f,0x44,0x00,0x00
.pushsection __mcount_loc,"a",@progbits
.quad 83457b
.popsection
.endm
/ Puts initialized data in uninitialized data section.
.macro .bsdata name:req expr:req bnd vis
.pushsection .initbss.300._init_\name,"aw",@nobits
\name: .quad 0
.endobj \name,\bnd,\vis
.popsection
.pushsection .initro.300._init_\name,"a",@progbits
.quad \expr
.popsection
.pushsection .init.300._init_\name,"ax",@progbits
_init_\name:
movsq
.endfn _init_\name
.popsection
.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,0xdb # xchg bx,bx (bochs breakpoint)
.byte 0x5b # pop bx
.byte 0x66,0x90 # xchg ax,ax (microsoft breakpoint)
int3 # gdb breakpoint
.endm
/ 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.
.macro yoink symbol:req
.pushsection .yoink
nop "\symbol"
.popsection
.endm
.macro .yoink symbol:req
.pushsection .yoink
nop "\symbol"
.popsection
.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