BLINK(1)
BLINK(1) โ General Commands Manual ๐
okay bestie, you found the blink(1) page from the General Commands Manual โจ and itโs literally giving โheadless blinkenlights x86-64-linux virtual machineโ energy. Letโs unpack every flag, path, quirk, and tiny detail together ๐ซถ.
๐ธ NAME ๐ธ
blink โ headless blinkenlights x86-64-linux virtual machine ๐
๐ SYNOPSIS ๐
blink [-hvjemZs] [-L logfile] [-C chroot] program [argv1...]
blink [-hvjemZs] [-L logfile] [-C chroot] -0 program [argv0...]
๐ฆ DESCRIPTION ๐ฆ
blink is a JITing virtual machine that uses x86_64 as its byte code language and implements the Linux Kernel ABI. It may be used to run prebuilt binaries intended for x86_64 Linux on other POSIX platforms. Thatโs the whole main-character setup, no cap โจ.
๐ ARGUMENTS ๐
The program argument is a PATH searched command, which may be:
- An
x86_64-linuxELF executable (either static or dynamic) - An Actually Portable Executable (either
MZqFpDorjartsrmagic) - A flat executable (if
programends with.bin,.img, or.raw) - A shell script whose
#!interpretermeets the above criteria
The -0 flag allows argv[0] to be specified on the command line. Under normal circumstances,
blink cmd arg1
is equivalent to
execve("cmd", {"cmd", "arg1"})
since thatโs how most programs are launched. However if you need the full power of execve() process spawning, you can say
blink -0 cmd arg0 arg1
which is equivalent to
execve("cmd", {"arg0", "arg1"})
๐ OPTIONS ๐
The following options are available:
-hโ prints condensed help. Short and sweet, bestie ๐-vโ showsblinkversion and build configuration details. The receipts โจ-eโ log to standard error (fd2) in addition to the log file. If logging to only standard error is desired, then-eL/dev/nullmay be passed as flags. Lowkey a little code-sneaky, but itโs right there ๐-sโ enables system call logging (repeatable).
This will emit to the log file the names of system calls each time a SYSCALL instruction is executed, along with its arguments and result. System calls are logged once theyโve completed, so that the result can be shown.
System calls are also sometimes logged upon entry too, in which case syscall(arg) -> ... will be logged to show that the system call has not yet completed. Whether or not this happens depends on how many times the -s flag is supplied.
- Passing
-s(once) will only log the entries of system calls that are defined as having read + write parameters (e.g.poll,select) - Passing
-ss(twice) will also log the entries of cancellation points that are likely to block (e.g.read,accept,wait,pause). - Passing
-sss(thrice) will log the entries of system calls that POSIX defines as cancellation points but are unlikely to block (e.g.write,close,open) which we try to avoid doing in order to reduce log noise. - Passing
-ssss(4x) will log the entry of every single system call, even harmless ones that have no business being emitted to the log twice (e.g.sigaction). This should only be useful for the Blink dev team when the rare need arises to troubleshoot a system call thatโs crashing.
Heads up: system call logging isnโt available in MODE=rel and MODE=tiny builds, in which case this flag is ignored.
-mโ enables full memory virtualization. Under normal circumstances,blinkaims to share the same address space as the guest program. Depending on the programโs memory requirements (i.e. if it usesMAP_FIXED) and the constraints imposed by the host platform, this so-called linear memory optimization may lead to anmmap()crisis that causes Blink to not work properly. Using this option will causeblinkto virtualize thex86_64address space precisely and reliably, however the use of this flag carries the tradeoff of causingblinkto go at least2xslower. Worth it when you need it, but the slowdown is real ๐ญ-jโ disables Just-In-Time (JIT) compilation. Using this option will causeblinkto go~10xor possibly even~100xslower. Iconic for debugging, tragic for speed ๐-Lpath โ specifies the log path. The default log path isblink.login the current directory at startup. This log file wonโt be created until something is actually logged. If logging to a file isnโt desired, then-L /dev/nullmay be used. See also the-eflag for logging to standard error.-Cpath โ launchprogramin a chrootโd environment. This flag is both equivalent to and overrides theBLINK_OVERLAYSenvironment variable.-Zโ prints internal statistics to standard error on exit. Each line will display a monitoring metric. Most metrics will either be integer counters or floating point running averages. Most but not all integer counters are monotonic. In the interest of not negatively impacting Blinkโs performance, statistics are computed on a best effort basis which currently isnโt guaranteed to be atomic in a multi-threaded environment. Statistics arenโt available inMODE=relandMODE=tinybuilds, in which case this flag is ignored.
๐ ENVIRONMENT ๐
The following environment variables are recognized:
BLINK_LOG_FILENAMEโ may be specified to supply a log path to be used in cases where the-L pathflag isnโt specified. This value should be an absolute path. If logging to standard error is desired, use the-eflag.BLINK_OVERLAYSโ specifies one or more directories to use as the root filesystem. Similar toPATHthis is a colon delimited list of pathnames. If relative paths are specified, theyโll be resolved to an absolute path at startup time. Overlays only apply to IO system calls that specify an absolute path. The empty string overlay means use the normal/root filesystem. The default value is:owhich means if the absolute path/$fis opened, then first check if/$fexists, and if it doesnโt, then check ifo/$fexists, in which case open that instead. Blink uses this convention to open shared object tests. It favors the system version if it exists, but also downloadsld-musl-x86_64.so.1too/lib/ld-musl-x86_64.so.1so the dynamic linker can transparently find it on platforms like Apple, that donโt let users put files in the root folder. On the other hand, itโs possible to sayBLINK_OVERLAYS=o:so thato/...takes precedence over/...(noting again that empty string means root). If a single overlay is specified that isnโt empty string, then itโll effectively act as a restricted chroot environment.
๐ช๏ธ QUIRKS ๐ช๏ธ
Hereโs the current list of Blinkโs known quirks and tradeoffs.
๐ฉ Flags ๐ฉ
Flag dependencies may not carry across function call boundaries under long mode. This is because when Blinkโs JIT is speculating whether or not itโs necessary for an arithmetic instruction to compute flags, it considers RET and CALL terminal ops that break the chain. As such 64-bit code shouldnโt do things we did in the DOS days, such as using carry flag as a return value to indicate error. This should work fine when STC is used to set the carry flag, but if the code computes it cleverly using instructions like SUB then EFLAGS might not change.
๐ Faults ๐
Blink may not report the precise program counter where a fault occurred in ucontext_t::uc_mcontext::rip when signalling a segmentation fault. This is currently only possible when PUSH or POP access bad memory. Thatโs because Blinkโs JIT tries to avoid updating Machine::ip on ops it considers โpureโ such as those that only access registers, which for reasons of performance is defined to include pushing and popping.
๐งต Threads ๐งต
Blink doesnโt have a working implementation of set_robust_list() yet, which means robust mutexes might not get unlocked if a process crashes.
๐ Coherency ๐
POSIX.1 provides almost no guarantees of coherency, synchronization, and durability when it comes to MAP_SHARED mappings and recommends that msync() be explicitly used to synchronize memory with file contents. The Linux Kernel implements shared memory so well, that this is rarely necessary. However some platforms like OpenBSD lack write coherency. This means if you change a shared writable memory map and then call pread() on the associated file region, you might get stale data. Blink isnโt able to polyfill incoherent platforms to be as coherent as Linux, therefore apps that run in Blink should assume the POSIX rules apply.
๐ก Signal Handling ๐ก
Blink uses SIGSYS to deliver signals internally. This signal is precious to Blink. Itโs currently not possible for guest applications to capture it from external processes.
๐ก๏ธ Memory Protection ๐ก๏ธ
Blink offers guest programs a 48-bit virtual address space with a 4096-byte page size. When programs are run on (1) host systems that have a larger page (e.g. Apple M1, Cygwin), and (2) the linear memory optimization is enabled (i.e. youโre not using blink -m) then Blink may need to relax memory protections in cases where the memory intervals defined by the guest arenโt aligned to the host system page size. Itโs recommended, when calling functions like mmap() and mprotect(), that both addr and addr + size be aligned to the true page size, which Blink reports to the guest in getauxval(AT_PAGESZ). This value should be obtainable via the portable API sysconf(_SC_PAGESIZE) assuming the C library implements it correctly. Please note that when Blink is running in its fully virtualized mode (i.e. blink -m) this concern does not apply. Thatโs because Blink will allocate a full system page for every 4096 byte page that gets mapped from a file.
๐ช EXIT STATUS ๐ช
The blink command passes along the exit code of the program which by convention is 0 on success or >0 on failure. In the event that blink fails to launch program the status 127 shall be returned.
๐ SEE ALSO ๐
๐ STANDARDS ๐
The blink command implements a superset of the IEEE Std 1003.1-2008 (โPOSIX.1โ) specification, intended to emulate the behaviors of the Linux Kernel.
๐ AUTHORS ๐
Justine Alexandra Roberts Tunney <jtunney@gmail.com> โ literally the author, slay ๐
source/version: Debian โ date: March 6, 2023 โ manual: BLINK(1) โ ok bye bestie, go run something iconic ๐โจ๐ฆ
๐ฆ where this page comes from
- nixos 26.05: blink 1.1.0
- nixpkgs unstable: blink 1.1.0
- Copyright 2023 Justine Alexandra Roberts Tunney
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms