[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6348":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":9,"rankLanguage":9,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":24,"topics":25,"createdAt":9,"pushedAt":9,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":15,"starSnapshotCount":15,"syncStatus":29,"lastSyncTime":30,"discoverSource":31},6348,"blink","jart\u002Fblink","jart","tiniest x86-64-linux emulator",null,"C",7525,265,65,41,0,4,18,27,23,38.27,"ISC License",false,"master",true,[],"2026-06-12 02:01:18","![Screenshot of Blink running GCC 9.4.0](blink\u002Fblink-gcc.png)\n\n# Blinkenlights\n\nThis project contains two programs:\n\n`blink` is a virtual machine that runs x86-64-linux programs on\ndifferent operating systems and hardware architectures. It's designed to\ndo the same thing as the `qemu-x86_64` command, except that\n\n1. Blink is 221kb in size (115kb with optional features disabled),\n   whereas qemu-x86_64 is a 4mb binary.\n\n2. Blink will run your Linux binaries on any POSIX system, whereas\n   qemu-x86_64 only supports Linux.\n\n3. Blink goes 2x faster than qemu-x86_64 on some benchmarks, such as SSE\n   integer \u002F floating point math. Blink is also much faster at running\n   ephemeral programs such as compilers.\n\n[`blinkenlights`](https:\u002F\u002Fjustine.lol\u002Fblinkenlights) is a terminal user\ninterface that may be used for debugging x86_64-linux or i8086 programs\nacross platforms. Unlike GDB, Blinkenlights focuses on visualizing\nprogram execution. It uses UNICODE IBM Code Page 437 characters to\ndisplay binary memory panels, which change as you step through your\nprogram's assembly code. These memory panels may be scrolled and zoomed\nusing your mouse wheel. Blinkenlights also permits reverse debugging,\nwhere scroll wheeling over the assembly display allows the rewinding of\nexecution history.\n\n## Getting Started\n\nWe regularly test that Blink is able run x86-64-linux binaries on the\nfollowing platforms:\n\n- Linux (x86, ARM, RISC-V, MIPS, PowerPC, s390x)\n- macOS (x86, ARM)\n- FreeBSD\n- OpenBSD\n- Cygwin\n\nBlink depends on the following libraries:\n\n- libc (POSIX.1-2017 with XSI extensions)\n\nBlink can be compiled on UNIX systems that have:\n\n- A C11 compiler with atomics (e.g. GCC 4.9.4+)\n- Modern GNU Make (i.e. not the one that comes with XCode)\n\nThe instructions for compiling Blink are as follows:\n\n```sh\n.\u002Fconfigure\nmake -j4\ndoas make install  # note: doas is modern sudo\nblink -v\nman blink\n```\n\nHere's how you can run a simple hello world program with Blink:\n\n```sh\nblink third_party\u002Fcosmo\u002Ftinyhello.elf\n```\n\nBlink has a debugger TUI, which works with UTF-8 ANSI terminals. The\nmost important keystrokes in this interface are `?` for help, `s` for\nstep, `c` for continue, and scroll wheel for reverse debugging.\n\n```sh\nblinkenlights third_party\u002Fcosmo\u002Ftinyhello.elf\n```\n\n### Alternative Builds\n\nFor maximum tinyness, use `MODE=tiny`, since it makes Blink's binary\nfootprint 50% smaller. The Blink executable should be on the order of\n200kb in size. Performance isn't impacted. Please note that all\nassertions will be removed, as well as all logging. Use this mode if\nyou're confident that Blink is bug-free for your use case.\n\n```sh\nmake MODE=tiny\nstrip o\u002Ftiny\u002Fblink\u002Fblink\nls -hal o\u002Ftiny\u002Fblink\u002Fblink\n```\n\nSome distros configure their compilers to add a lot of security bloat,\nwhich might add 60kb or more to the above binary size. You can work\naround that by using one of Blink's toolchains. This should produce\nconsistently the smallest possible executable size.\n\n```sh\nmake MODE=tiny o\u002Ftiny\u002Fx86_64\u002Fblink\u002Fblink\no\u002Fthird_party\u002Fgcc\u002Fx86_64\u002Fbin\u002Fx86_64-linux-musl-strip o\u002Ftiny\u002Fx86_64\u002Fblink\u002Fblink\nls -hal o\u002Ftiny\u002Fx86_64\u002Fblink\u002Fblink\n```\n\nIf you want to make Blink *even tinier* (more on the order of 120kb\nrather than 200kb) than you can tune the `.\u002Fconfigure` script to disable\noptional features such as jit, threads, sockets, x87, bcd, xsi, etc.\n\n```sh\n.\u002Fconfigure --disable-all --posix\nmake MODE=tiny o\u002Ftiny\u002Fx86_64\u002Fblink\u002Fblink\no\u002Fthird_party\u002Fgcc\u002Fx86_64\u002Fbin\u002Fx86_64-linux-musl-strip o\u002Ftiny\u002Fx86_64\u002Fblink\u002Fblink\nls -hal o\u002Ftiny\u002Fx86_64\u002Fblink\u002Fblink\n```\n\nThe traditional `MODE=rel` or `MODE=opt` modes are available. Use this\nmode if you're on a non-JIT architecture (since this won't improve\nperformance on AMD64 and ARM64) and you're confident that Blink is\nbug-free for your use case, and would rather have Blink not create a\n`blink.log` or print `SIGSEGV` delivery warnings to standard error,\nsince many apps implement their own crash reporting.\n\n```sh\nmake MODE=rel\no\u002Frel\u002Fblink\u002Fblink -h\n```\n\nYou can hunt down bugs in Blink using the following build modes:\n\n- `MODE=asan` helps find memory safety bugs\n- `MODE=tsan` helps find threading related bugs\n- `MODE=ubsan` to find violations of the C standard\n- `MODE=msan` helps find uninitialized memory errors\n\nYou can check Blink's compliance with the POSIX standard using the\nfollowing configuration flags:\n\n```sh\n.\u002Fconfigure --posix  # only use c11 with posix xopen standard\n```\n\nIf you want to run a full `chroot`'d Linux distro and require correct\nhandling of absolute symlinks, displaying of certain values in `\u002Fproc`,\nand so on, and you don't mind paying a small price in terms of size\nand performance, you can enable the emulated VFS feature by using\nthe following configuration:\n\n```sh\n.\u002Fconfigure --enable-vfs\n```\n\n### Testing\n\nBlink is tested primarily using precompiled binaries downloaded\nautomatically. Blink has more than 700 test programs total. You can\ncheck how well Blink works on your local platform by running:\n\n```sh\nmake check\n```\n\nTo check that Blink works on 11 different hardware `$(ARCHITECTURES)`\n(see [Makefile](Makefile)), you can run the following command, which\nwill download statically-compiled builds of GCC and Qemu. Since our\ntoolchain binaries are intended for x86-64 Linux, Blink will bootstrap\nitself locally first, so that it's possible to run these tests on other\noperating systems and architectures.\n\n```sh\nmake check2\nmake emulates\n```\n\n### Production Worthiness\n\nBlink passes 194 test suites from the Cosmopolitan Libc project (see\n[third_party\u002Fcosmo](third_party\u002Fcosmo)). Blink passes 350 test suites\nfrom the [Linux Test Project](https:\u002F\u002Fgithub.com\u002Flinux-test-project\u002Fltp)\n(see [third_party\u002Fltp](third_party\u002Fltp)). Blink passes 108 of [Musl\nLibc's unit test suite](https:\u002F\u002Fgithub.com\u002Fjart\u002Flibc-test) (see\n[third_party\u002Flibc-test](third_party\u002Flibc-test)). The tests we haven't\nincluded are because either (1) it wanted x87 long double to have 80-bit\nprecision, or (2) it used Linux APIs we can't or won't support, e.g.\nSystem V message queues. Blink runs the precompiled Linux test binaries\nabove on other operating systems too, e.g. Apple M1, FreeBSD, Cygwin.\n\n## Reference\n\nThe Blinkenlights project provides two programs which may be launched on\nthe command line.\n\n### `blink` Flags\n\nThe headless Blinkenlights virtual machine command (named `blink` by\nconvention) accepts command line arguments per the specification:\n\n```\nblink [FLAG...] PROGRAM [ARG...]\n```\n\nWhere `PROGRAM` is an x86_64-linux binary that may be specified as:\n\n1. An absolute path to an executable file, which will be run as-is\n2. A relative path containing slashes, which will be run as-is\n3. A path name without slashes, which will be `$PATH` searched\n\nThe following `FLAG` arguments are provided:\n\n- `-h` shows help on command usage\n\n- `-v` shows version and build configuration details\n\n- `-e` means log to standard error (fd 2) in addition to the log file.\n  If logging to *only* standard error is desired, then `-eL\u002Fdev\u002Fnull`\n  may be used.\n\n- `-j` disables Just-In-Time (JIT) compilation, which will make Blink go\n  ~10x slower.\n\n- `-m` disables the linear memory optimization. This makes Blink memory\n  safe, but comes at the cost of going ~4x slower. On some platforms\n  this can help avoid the possibility of an mmap() crisis.\n\n- `-0` allows `argv[0]` to be specified on the command line. Under\n  normal circumstances, `blink cmd arg1` is equivalent to `execve(\"cmd\",\n  {\"cmd\", \"arg1\"})` since that's how most programs are launched. However\n  if you need the full power of execve() process spawning, you can say\n  `blink -0 cmd arg0 arg1` which is equivalent to `execve(\"cmd\",\n  {\"arg0\", \"arg1\"})`.\n\n- `-L PATH` specifies the log path. The default log path is `blink.log`\n  in the current directory at startup. This log file won't be created\n  until something is actually logged. If logging to a file isn't\n  desired, then `-L \u002Fdev\u002Fnull` may be used. See also the `-e` flag for\n  logging to standard error.\n\n- `-s` enables system call logging. This will emit to the log file the\n  names of system calls each time a SYSCALL instruction in executed,\n  along with its arguments and result. System calls are logged once\n  they've completed. If this option is specified twice, then system\n  calls which are likely to block (e.g. poll) will be logged at entry\n  too. If this option is specified thrice, then all cancellation points\n  will be logged upon entry. System call logging isn't available in\n  `MODE=rel` and `MODE=tiny` builds, in which case this flag is ignored.\n\n- `-Z` will cause internal statistics to be printed to standard error on\n  exit. Stats aren't available in `MODE=rel` and `MODE=tiny` builds, and\n  this flag is ignored.\n\n- `-C path` will cause blink to launch the program in a chroot'd\n  environment. This flag is both equivalent to and overrides the\n  `BLINK_OVERLAYS` environment variable. Note: This flag works\n  especially well if you use `.\u002Fconfigure --enable-vfs`.\n\n### `blinkenlights` Flags\n\nThe Blinkenlights ANSI TUI interface command (named `blinkenlights` by\nconvention) accepts its command line arguments in accordance with the\nfollowing specification:\n\n```\nblinkenlights [FLAG...] PROGRAM [ARG...]\n```\n\nWhere `PROGRAM` is an x86_64-linux binary that may be specified as:\n\n1. An absolute path to an executable file, which will be run as-is\n2. A relative path containing slashes, which will be run as-is\n3. A path name without slashes, which will be `$PATH` searched\n\nThe following `FLAG` arguments are provided:\n\n- `-h` shows help on command usage\n\n- `-v` shows version and build configuration details\n\n- `-r` puts your virtual machine in real mode. This may be used to run\n  16-bit i8086 programs, such as SectorLISP. It's also used for booting\n  programs from Blinkenlights's simulated BIOS.\n\n- `-b ADDR` pushes a breakpoint, which may be specified as a raw\n  hexadecimal address, or a symbolic name that's defined by your ELF\n  binary (or its associated `.dbg` file). When pressing `c` (continue)\n  or `C` (continue harder) in the TUI, Blink will immediately stop upon\n  reaching an instruction that's listed as a breakpoint, after which a\n  modal dialog is displayed. The modal dialog may be cleared by `ENTER`\n  after which the TUI resumes its normal state.\n\n- `-w ADDR` pushes a watchpoint, which may be specified as a raw\n  hexadecimal address, or a symbolic name that's defined by your ELF\n  binary (or its associated `.dbg` file). When pressing `c` (continue)\n  or `C` (continue harder) in the TUI, Blink will immediately stop upon\n  reaching an instruction that either (a) has a ModR\u002FM encoding that\n  references an address that's listed as a watchpoint, or (b) manages to\n  mutate the memory stored at a watchpoint address by some other means.\n  When Blinkenlights is stopped at a watchpoint, a modal dialog will be\n  displayed which may be cleared by pressing `ENTER`, after which the\n  TUI resumes its normal state.\n\n- `-j` enables Just-In-Time (JIT) compilation. This will make\n  Blinkenlights go significantly faster, at the cost of taking away the\n  ability to step through each instruction. The TUI will visualize JIT\n  path formation in the assembly display; see the JIT Path Glyphs\n  section below to learn more. Please note this flag has the opposite\n  meaning as it does in the `blink` command.\n\n- `-m` enables the linear memory optimization. This makes blinkenlights\n  capable of faster emulation, at the cost of losing some statistics. It\n  no longer becomes possible to display which percentage of a memory map\n  has been activated. Blinkenlights will also remove the commit \u002F\n  reserve \u002F free page statistics from the status panel on the bottom\n  right of the display. Please note this flag has the opposite meaning\n  as it does in the `blink` command.\n\n- `-t` may be used to disable Blinkenlights TUI mode. This makes the\n  program behave similarly to the `blink` command, however not as good.\n  We're currently using this flag for unit testing real mode programs,\n  which are encouraged to use the `SYSCALL` instruction to report their\n  exit status.\n\n- `-L PATH` specifies the log path. The default log path is\n  `$TMPDIR\u002Fblink.log` or `\u002Ftmp\u002Fblink.log` if `$TMPDIR` isn't defined.\n\n- `-C path` will cause blink to launch the program in a chroot'd\n  environment. This flag is both equivalent to and overrides the\n  `BLINK_OVERLAYS` environment variable.\n\n- `-s` enables system call logging. This will emit to the log file the\n  names of system calls each time a SYSCALL instruction in executed,\n  along with its arguments and result. System calls are logged once\n  they've completed. If this option is specified twice, then system\n  calls which are likely to block (e.g. poll) will be logged at entry\n  too. If this option is specified thrice, then all cancellation points\n  will be logged upon entry. System call logging isn't available in\n  `MODE=rel` and `MODE=tiny` builds, in which case this flag is ignored.\n\n- `-Z` will cause internal statistics to be printed to standard error on\n  exit. Each line will display a monitoring metric. Most metrics will\n  either be integer counters or floating point running averages. Most\n  but not all integer counters are monotonic. In the interest of not\n  negatively impacting Blink's performance, statistics are computed on a\n  best effort basis which currently isn't guaranteed to be atomic in a\n  multi-threaded environment. Stats aren't available in `MODE=rel` and\n  `MODE=tiny` builds, and this flag is ignored.\n\n- `-z` [repeatable] may be specified to zoom the memory panels, so they\n  display a larger amount of memory in a smaller space. By default, one\n  terminal cell corresponds to a single byte of memory. When memory has\n  been zoomed the magic kernel is used (similar to Lanczos) to decimate\n  the number of bytes by half, for each `-z` that's specified. Normally\n  this would be accomplished by using `CTRL+MOUSEWHEEL` where the mouse\n  cursor is hovered over the panel that should be zoomed. However, many\n  terminal emulators (especially on Windows), do not support this xterm\n  feature and as such, this flag is provided as an alternative.\n\n- `-V` [repeatable] increases verbosity\n\n- `-R` disables reactive error mode\n\n- `-H` disables syntax highlighting\n\n- `-N` enables natural scrolling\n\n### Recommended Environments\n\nBlinkenlights' TUI requires a UTF-8 VT100 \u002F XTERM style terminal to use.\nWe recommend the following terminals, ordered by preference:\n\n- [KiTTY](https:\u002F\u002Fsw.kovidgoyal.net\u002Fkitty\u002F) (Linux)\n- [PuTTY](https:\u002F\u002Fwww.chiark.greenend.org.uk\u002F~sgtatham\u002Fputty\u002Flatest.html) (Windows)\n- Gnome Terminal (Linux)\n- Terminal.app (macOS)\n- CMD.EXE (Windows 10+)\n- PowerShell (Windows 10+)\n- Xterm (Linux)\n\nThe following fonts are recommended, ordered by preference:\n\n- [PragmataPro Regular Mono](https:\u002F\u002Ffsd.it\u002Fshop\u002Ffonts\u002Fpragmatapro\u002F) (€59)\n- Bitstream Vera Sans Mono (a.k.a. DejaVu Sans Mono)\n- Consolas\n- Menlo\n\n#### JIT Path Glyphs\n\nWhen the Blinkenlights TUI is run with JITing enabled (using the `-j`\nflag) the assembly dump display will display a glyph next to the address\nof each instruction, to indicate the status of JIT path formation. Those\nglyphs are defined as follows:\n\n- ` ` or space indicates no JIT path is associated with an address\n\n- `S` means that a JIT path is currently being constructed which\n  starts at this address. By continuing to press `s` (step) in the TUI\n  interface, the JIT path will grow longer until it is eventually\n  completed, and the `S` glyph is replaced by `*`.\n\n- `*` (asterisk) means that a JIT path has been installed to the\n  adjacent address. When `s` (step) is pressed at such addresses\n  within the TUI display, stepping takes on a different meaning.\n  Rather than stepping a single instruction, it will step the entire\n  length of the JIT path. The next assembly line that'll be\n  highlighted will be the instruction after where the path ends.\n\n### Environment Variables\n\nThe following environment variables are recognized by both the `blink`\nand `blinkenlights` commands:\n\n- `BLINK_LOG_FILENAME` may be specified to supply a log path to be used\n  in cases where the `-L PATH` flag isn't specified. This value should\n  be an absolute path. If logging to standard error is desired, use the\n  `blink -e` flag.\n\n- `BLINK_OVERLAYS` specifies one or more directories to use as the root\n  filesystem. Similar to `$PATH` this is a colon delimited list of\n  pathnames. If relative paths are specified, they'll be resolved to an\n  absolute path at startup time. Overlays only apply to IO system calls\n  that specify an absolute path. The empty string overlay means use the\n  normal `\u002F` root filesystem. The default value is `:o`, which means if\n  the absolute path `\u002F$f` is opened, then first check if `\u002F$f` exists,\n  and if it doesn't, then check if `o\u002F$f` exists, in which case open\n  that instead. Blink uses this convention to open shared object tests.\n  It favors the system version if it exists, but also downloads\n  `ld-musl-x86_64.so.1` to `o\u002Flib\u002Fld-musl-x86_64.so.1` so the dynamic\n  linker can transparently find it on platforms like Apple, that don't\n  let users put files in the root folder. On the other hand, it's\n  possible to say `BLINK_OVERLAYS=o:` so that `o\u002F...` takes precedence\n  over `\u002F...` (noting again that empty string means root). If a single\n  overlay is specified that isn't empty string, then it'll effectively\n  act as a restricted chroot environment.\n\n## Compiling and Running Programs under Blink\n\nBlink can be picky about which Linux binaries it'll execute. It may also\nbe the case that your Linux binary will only run under Blink on Linux,\nbut report errors if run under Blink on another platform, e.g. macOS. In\nour experience, how successfully a program can run under Blink depends\nalmost entirely on (1) how it was compiled, and (2) which C library it\nuses. This section will provide guidance on which tools will work best.\n\nFirst, some background. Blink's coverage of the x86_64 instruction set\nis comprehensive. However the Linux system call ABI is much larger and\ntherefore not possible to fully support, unless Blink emulated a Linux\nkernel image too. Blink has sought to support the subset of Linux ABIs\nthat are either (1) standardized by POSIX.1-2017 or (2) too popular to\n*not* support. As an example, `AF_INET`, `AF_UNIX`, and `AF_INET6` are\nsupported, but Blink will return `EINVAL` if a program requests any of\nthe dozens of other ones, e.g. `AF_BLUETOOTH`. Such errors are usually\nlogged to `\u002Ftmp\u002Fblink.log`, to make it easy to file a feature request.\nIn other cases ABIs aren't supported simply because they're Linux-only\nand difficult to polyfill on other POSIX platforms. For example, Blink\nwill polyfill `open(O_TMPFILE)` on non-Linux platforms so it works the\nsame way, but other Linux-specific ABIs like `membarrier()` we haven't\nhad the time to figure out yet. Since app developers usually don't use\nnon-portable APIs, it's usually the platform C library that's at fault\nfor calling them. Many Linux system calls, could be rightfully thought\nof as an implementation detail of Glibc.\n\nBlink's prime directive is to support binaries built with Cosmopolitan\nLibc. Actually Portable Executables make up the bulk of Blink's unit\ntest suite. Anything created by Cosmopolitan is almost certainly going\nto work very well. Since Cosmopolitan is closely related to Musl Libc,\nprograms compiled using Musl also tend to work very well. For example,\nAlpine Linux is a Musl Libc based distro, so their prebuilt dynamic\nbinaries tend to all work well, and it's also a great platform to use\nfor compiling other software from source that's intended for Blink.\n\nSo the recommended approach is either:\n\n1. Build your app using Cosmopolitan Libc, otherwise\n2. Build your app using GNU Autotools on Alpine Linux\n3. Build your app using Buildroot\n\nFor Cosmopolitan, please read [Getting Started with Cosmopolitan\nLibc](https:\u002F\u002Fjeskin.net\u002Fblog\u002Fgetting-started-with-cosmopolitan-libc\u002F)\nfor information on how to get started. Cosmopolitan comes with a lot of\nthird party software included that you can try with Blink right away,\ne.g. SQLite, Python, QuickJS, and Antirez's Kilo editor.\n\n```\ngit clone https:\u002F\u002Fgithub.com\u002Fjart\u002Fcosmopolitan\u002F\ncd cosmopolitan\n\nmake -j8 o\u002F\u002Fthird_party\u002Fpython\u002Fpython.com\nblinkenlights -jm o\u002F\u002Fthird_party\u002Fpython\u002Fpython.com\n\nmake -j8 o\u002F\u002Fthird_party\u002Fquickjs\u002Fqjs.com\nblinkenlights -jm o\u002F\u002Fthird_party\u002Fquickjs\u002Fqjs.com\n\nmake -j8 o\u002F\u002Fthird_party\u002Fsqlite3\u002Fsqlite3.com\nblinkenlights -jm o\u002F\u002Fthird_party\u002Fsqlite3\u002Fsqlite3.com\n\nmake -j8 o\u002F\u002Fexamples\u002Fkilo.com\nblinkenlights -jm o\u002F\u002Fexamples\u002Fkilo.com\n```\n\nBlink is great for making single-file autonomous binaries like the above\neasily copyable across platforms. If you're more interested in building\nsystems instead, then [Buildroot](https:\u002F\u002Fbuildroot.org\u002F) is one way to\ncreate a Linux userspace that'll run under Blink. All you have to do is\nset the `$BLINK_OVERLAYS` environment variable to the buildroot target\nfolder, which will ask Blink to create a chroot'd environment.\n\n```\ncd ~\u002Fbuildroot\nexport CC=\"gcc -Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\nmake menuconfig\nmake\ncp -R output\u002Ftarget ~\u002Fblinkroot\ndoas mount -t devtmpfs none ~\u002Fblinkroot\u002Fdev\ndoas mount -t sysfs none ~\u002Fblinkroot\u002Fsys\ndoas mount -t proc none ~\u002Fblinkroot\u002Fproc\ncd ~\u002Fblink\nmake -j8\nexport BLINK_OVERLAYS=$HOME\u002Fblinkroot\nblink sh\nuname -a\nLinux hostname 4.5 blink-1.0 x86_64 GNU\u002FLinux\n```\n\nIf you want to build an Autotools project like Emacs, the best way to do\nthat is to spin up an Alpine Linux container and use\n[jart\u002Fblink-isystem](https:\u002F\u002Fgithub.com\u002Fjart\u002Fblink-isystem) as your\nsystem header subset. blink-isystem is basically just the Musl Linux\nheaders with all the problematic APIs commented out. That way autoconf\nwon't think the APIs Blink doesn't have are available, and will instead\nconfigure Emacs to use portable alternatives. Setting this up is simple:\n\n```\n.\u002Fconfigure CFLAGS=\"-isystem $HOME\u002Fblink-isystem\" \\\n            CXXFLAGS=\"-isystem $HOME\u002Fblink-isystem\" \\\n            LDFLAGS=\"-static -Wl,-z,common-page-size=65536,-z,max-page-size=65536\"\nmake -j\n```\n\nAnother big issue is the host system page size may cause problems on\nnon-Linux platforms like Apple M1 (16kb) and Cygwin (64kb). On such\nplatforms, you may encounter an error like this:\n\n```\np_vaddr p_offset skew unequal w.r.t. host page size\n```\n\nThe simplest way to solve that is by disabling the linear memory\noptimization (using the `blink -m` flag) but that'll slow down\nperformance. Another option is to try recompiling your executable so\nthat its ELF program headers will work on systems with a larger page\nsize. You can do that using these GCC flags:\n\n```\ngcc -static -Wl,-z,common-page-size=65536,-z,max-page-size=65536 ...\n```\n\nHowever that's just step one. The program also needs to be using APIs\nlike `sysconf(_SC_PAGESIZE)` which will return the true host page size,\nrather than naively assuming it's 4096 bytes. Your C library gets this\ninformation from Blink via `getauxval(AT_PAGESZ)`.\n\nIf you're using the Blinkenlights debugger TUI, then another important\nset of flags to use are the following:\n\n- `-fno-omit-frame-pointer`\n- `-mno-omit-leaf-frame-pointer`\n\nBy default, GCC and Clang use the `%rbp` backtrace pointer as a general\npurpose register, and as such, Blinkenlights won't be able to display a\nframes panel visualizing your call stack. Using those flags solves that.\nHowever it's tricky sometimes to correctly specify them in a complex\nbuild environment, where other optimization flags might subsequently\nturn them back off again.\n\nThe trick we recommend using for compiling your programs, is to create a\nshell script that wraps your compiler command, and then use the script\nin your `$CC` environment variable. The script should look something\nlike the following:\n\n```sh\n#!\u002Fbin\u002Fsh\nset \u002Fusr\u002Fbin\u002Fgcc \"$@\" -g \\\n    -fno-omit-frame-pointer \\\n    -fno-optimize-sibling-calls \\\n    -mno-omit-leaf-frame-pointer \\\n    -Wl,-z,norelro \\\n    -Wl,-z,noseparate-code \\\n    -Wl,-z,max-page-size=65536 \\\n    -Wl,-z,common-page-size=65536\nprintf '%s\\n' \"$*\" >>\u002Ftmp\u002Fgcc.log\nexec \"$@\"\n```\n\nThose flags will go a long way towards helping your Linux binaries be\n(1) capable of running under Blink on all of its supported operating\nsystems and microprocessor architectures, and (2) trading away some of\nthe modern security blankets in the interest of making the assembly\npanel more readable, and less likely to be picky about memory.\n\nIf you're a Cosmopolitan Libc user, then Cosmopolitan already provides\nsuch a script, which is the `cosmocc` and `cosmoc++` toolchain. Please\nnote that Cosmopolitan Libc uses a 64kb page size so it isn't impacted\nby many of these issues that Glibc and Musl users may experience.\n\n- [cosmopolitan\u002Ftool\u002Fscripts\u002Fcosmocc](https:\u002F\u002Fgithub.com\u002Fjart\u002Fcosmopolitan\u002Fblob\u002Fmaster\u002Ftool\u002Fscripts\u002Fcosmocc)\n- [cosmopolitan\u002Ftool\u002Fscripts\u002Fcosmoc++](https:\u002F\u002Fgithub.com\u002Fjart\u002Fcosmopolitan\u002Fblob\u002Fmaster\u002Ftool\u002Fscripts\u002Fcosmoc%2B%2B)\n\nIf you're not a C \u002F C++ developer, and you prefer to use high-level\nlanguages instead, then one program you might consider emulating is\nActually Portable Python, which is an APE build of the CPython v3.6\ninterpreter. It can be built from source, and then used as follows:\n\n```\ngit clone https:\u002F\u002Fgithub.com\u002Fjart\u002Fcosmopolitan\u002F\ncd cosmopolitan\nmake -j8 o\u002F\u002Fthird_party\u002Fpython\u002Fpython.com\nblinkenlights -jm o\u002F\u002Fthird_party\u002Fpython\u002Fpython.com\n```\n\nThe `-jm` flags are helpful here, since they ask the Blinkenlights TUI\nto enable JIT and the linear memory optimization. It's helpful to have\nthose flags because Python is a very complicated and compute intensive\nprogram, that would otherwise move too slowly under the Blinkenlights\nvizualization. You may also want to press the `CTRL-T` (TURBO) key a few\ntimes, to make Python emulate in the TUI even faster.\n\n## Technical Details\n\nblink is an x86-64 interpreter for POSIX platforms that's written in\nANSI C11 that's compatible with C++ compilers. Instruction decoding is\ndone using our trimmed-down version of Intel's disassembler Xed.\n\nThe prime directive of this project is to act as a virtual machine for\nuserspace binaries compiled by Cosmopolitan Libc. However we've also had\nsuccess virtualizing programs compiled with Glibc and Musl Libc, such as\nGCC and Qemu. Blink supports 500+ instructions and 150+ Linux syscalls,\nincluding fork() and clone(). Linux system calls may only be used by\nlong mode programs via the `SYSCALL` instruction, as it is written in\nthe System V ABI.\n\n### Instruction Sets\n\nThe following hardware ISAs are supported by Blink.\n\n- i8086\n- i386\n- X87\n- SSE2\n- x86_64\n- SSE3\n- SSSE3\n- CLMUL\n- POPCNT\n- ADX\n- BMI2\n- RDRND\n- RDSEED\n- RDTSCP\n\nPrograms may use `CPUID` to confirm the presence or absence of optional\ninstruction sets. Please note that Blink does not follow the same\nmonotonic progress as Intel's hardware. For example, BMI2 is supported;\nthis is an AVX2-encoded (VEX) instruction set, which Blink is able to\ndecode, even though the AVX2 ISA isn't supported. Therefore it's\nimportant to not glob ISAs into \"levels\" (as Windows software tends to\ndo) where it's assumed that BMI2 support implies AVX2 support; because\nwith Blink that currently isn't the case.\n\nOn the other hand, Blink does share Windows' x87 behavior w.r.t. double\n(rather than long double) precision. It's not possible to use 80-bit\nfloating point precision with Blink, because Blink simply passes along\nfloating point operations to the host architecture, and very few\narchitectures support `long double` precision. You can still use x87\nwith 80-bit words. Blink will just store 64-bit floating point values\ninside them, and that's a legal configuration according to the x87 FPU\ncontrol word. If possible, it's recommended that `long double` simply be\navoided. If 64-bit floating point [is good enough for the rocket\nscientists at\nNASA](https:\u002F\u002Fwww.jpl.nasa.gov\u002Fedu\u002Fnews\u002F2016\u002F3\u002F16\u002Fhow-many-decimals-of-pi-do-we-really-need\u002F)\nthen it should be good enough for everybody. There are some peculiar\ndifferences in behavior with `double` across architectures (which Blink\ncurrently does nothing to address) but they tend to be comparatively\nminor, e.g. an op returning `NAN` instead of `-NAN`.\n\nBlink has reasonably comprehensive coverage of the baseline ISAs,\nincluding even support for BCD operations (even in long mode!). But there\nare some truly fringe instructions Blink hasn't implemented, such as\n`BOUND` and `ENTER`. Most of the unsupported instructions, are usually\nring-0 system instructions, since Blink is primarily a user-mode VM, and\ntherefore only has limited support for bare metal operating system\nsoftware (which we'll discuss more in-depth in a later section).\n\nBlink advertises itself as `Linux 4.5` in the `uname()` system call and\n`uname -v` will report `blink-1.0`. Programs may detect they're running\nin Blink by issuing a `CPUID` instruction where `EAX` is set to the leaf\nnumber:\n\n- Leaf `0x0` (or `0x80000000`) reports `GenuineIntel` in\n  `EBX ‖ EDX ‖ ECX`\n\n- Leaf `0x1` reports that Blink is a hypervisor in bit `31` of `ECX`\n\n- Leaf `0x40000000` reports `GenuineBlink` as the hypervisor name in\n  `EBX ‖ ECX ‖ EDX`\n\n- Leaf `0x40031337` reports the underlying operating system name in\n  `EBX ‖ ECX ‖ EDX` with zero filling for strings shorter than 12:\n\n  - `Linux` for Linux\n  - `XNU` for macOS\n  - `FreeBSD` for FreeBSD\n  - `NetBSD` for NetBSD\n  - `OpenBSD` for OpenBSD\n  - `Linux` for Linux\n  - `Cygwin` for Windows under Cygwin\n  - `Windows` for Windows under Cosmopolitan\n  - `Unknown` if compiled on unrecognized platform\n\n- Leaf `0x40031338` reports the underlying hardware architecture name\n  in `EBX ‖ ECX ‖ EDX` with zero filling for strings shorter than 12:\n\n  - `x86_64` for x86_64\n  - `i386` for i386\n  - `aarch64` for aarch64\n  - `arm` for arm32\n  - `ppc64` for powerpc64\n  - `ppc64le` for powerpc64le\n  - `ppc` for powerpc\n  - `s390x` for s390x\n  - `riscv64` for riscv64\n  - `riscv32` for riscv32\n  - `Unknown` if compiled on unrecognized platform\n\n- Leaf `0x80000001` tells if Blink's JIT is enabled in bit `31` in `ECX`\n\n### JIT\n\nBlink uses just-in-time compilation, which is supported on x86_64 and\naarch64. Blink takes the appropriate steps to work around restrictions\nrelating to JIT, on platforms like Apple and OpenBSD. We generate JIT\ncode using a printf-style domain-specific language. The JIT works by\ngenerating functions at runtime which call the micro-op functions the\ncompiler created. To make micro-operations go faster, Blink determines\nthe byte length of the compiled function at runtime by scanning for a\nRET instruction. Blink will then copy the compiled function into the\nfunction that the JIT is generating. This works in most cases, however\nsome tools can cause problems. For example, OpenBSD RetGuard inserts\nstatic memory relocations into every compiled function, which Blink's\nJIT currently doesn't understand; so we need to use compiler flags to\ndisable that type of magic. In the event other such magic slips through,\nBlink has a runtime check which will catch obvious problems, and then\ngracefully fall back to using a CALL instruction. Since no JIT can be\nfully perfect on all platforms, the `blink -j` flag may be passed to\ndisable Blink's JIT. Please note that disabling JIT makes Blink go 10x\nslower. With the `blinkenlights` command, the `-j` flag takes on the\nopposite meaning, where it instead *enables* JIT. This can be useful for\ntroubleshooting the JIT, because the TUI display has a feature that lets\nJIT path formation be visualized. Blink currently only enables the JIT\nfor programs running in long mode (64-bit) but we may support JITing\n16-bit programs in the future.\n\n### Virtualization\n\nBlink virtualizes memory using the same PML4T approach as the hardware\nitself, where memory lookups are indirected through a four-level radix\ntree. Since performing four separate page table lookups on every memory\naccess can be slow, Blink checks a translation lookaside buffer, which\ncontains the sixteen most recently used page table entries. The PML4T\nallows all memory lookups in Blink to be \"safe\" but it still doesn't\noffer the best possible performance. Therefore, on systems with a huge\naddress space (i.e. petabytes of virtual memory) Blink relies on itself\nbeing loaded to a random location, and then identity maps guest memory\nusing a simple linear translation. For example, if the guest virtual\naddress is `0x400000` then the host address might be\n`0x400000+0x088800000000`. This means that each time a memory operation\nis executed, only a simple addition needs to be performed. This goes\nextremely fast, however it may present issues for programs that use\n`MAP_FIXED`. Some systems, such as modern Raspberry Pi, actually have a\nlarger address space than x86-64, which lets Blink offer the guest the\ncomplete address space. However on some platforms, like 32-bit ones,\nonly a limited number of identity mappings are possible. There's also\ncompiler tools like TSAN which lay claim to much of the fixed address\nspace. Blink's solution is designed to meet the needs of Cosmopolitan\nLibc, while working around Apple's restriction on 32-bit addresses, and\nstill remain fully compatible with ASAN's restrictions. In the event\nthat this translation scheme doesn't work on your system, the `blink -m`\nflag may be passed to disable the linear translation optimization, and\ninstead use only the memory safe full virtualization approach of the\nPML4T and TLB.\n\n#### Lockless Hashing\n\nBlink stores generated functions by virtual address in a multithreaded\nlockless hash table. The hottest operation in the codebase is reading\nfrom this hash table, using a function called `GetJitHook`. Since it'd\nslow Blink down by more than 33% if a mutex were used here, Blink will\nsynchronize reads optimistically using only carefully ordered load\ninstructions, three of which have acquire semantics. This hash table\nstarts off at a reasonable size and grows gradually with the memory\nrequirements. This design is the primary reason Blink usually uses 40%\nless peak resident memory than Qemu.\n\n#### Acyclic Codegen\n\nEven though JIT paths will always end at branching instructions, Blink\nwill generate code so that paths tail call into each other, in order to\navoid dropping back into the main interpreter loop. The average length\nof a JIT path is about ~5 opcodes. Connecting paths causes the average\npath length to be ~13 opcodes.\n\nSince Blink only checks for asynchronous signal delivery and shutdown\nevents from the main interpreter loop, Blink maintains a bidirectional\nmap of edges between generated functions, so that path connections which\nwould result in cycles are never introduced.\n\nAn exception is made for tight conditional branches, i.e. jumps whose\ntaken path jump backwards to the start of the JIT path. Such branches\nare allowed to be self-referencing so that whole loops of non-system\noperations may be run in purely native code.\n\n#### Reliable Memory\n\nBlink has a 22mb global static variable that's set aside for JIT code.\nThis limit was chosen because that's roughly the maximum displacement\npermitted on Arm64 architecture. Having that memory near the program\nimage helps make Blink simpler, since generated functions call normal\nfunctions, without needing relocations or procedure linkage tables.\n\nWhen Blink runs out of JIT memory, it simply clears all JIT hooks and\nlets the whole code generation process start again. Blink is very fast\nat generating code, and it wouldn't make sense during an OOM panic to\narbitrarily choose a subset of pages to reset, since resetting pages\nrequires tracing their dependencies and resetting those too. Starting\nover is much better. It's so much better in fact, that even if Blink\nonly reserved less than a megabyte of memory for JIT, then the slowdown\nthat'd be incurred running 40mb binaries like GCC CC1 would only be 3x.\n\nBlink triggers the OOM panic when only 10% of its JIT memory remains.\nThat's because in multi-threaded programs, there's no way to guarantee\nnothing is still executing on the retired code blocks. Blink solves this\nby letting retired blocks cool off at the back of a freelist queue, so\nthe acyclicity invariant has abundant time to ensure threads drop out.\n\n### Self-Modifying Code\n\nMany CPU architectures require esoteric rituals for flushing CPU caches\nwhen code modifies itself. That's not the case with x86 architecture,\nwhich takes care of this chore automatically. Blink is able to offer the\nsame promises here as Intel and AMD, by abstracting fast and automatic\ninvalidation of caches for programs using self-modifying code (SMC).\n\nWhen Blink's JIT isn't enabled, self-modifying code always causes\ninstruction caches to be invalidated immediately, at least within the\nsame thread. That's because Blink compares the raw instruction bytes\nwith what's in the instruction cache before fetching its decoded value.\n\nWhen JITing is enabled, Blink will automatically invalidate JIT memory\nassociated with code that's been modified. This happens on a 4096-byte\npage granularity. When a function like mprotect() is called that causes\nmemory pages to transition from a non-executable to executable state,\nthe impacted pages will be invalidated by the JIT. The JIT maintains a\nhash table where the key is the virtual address at which a generated\nfunction begins (which we call a \"path\") and the value is a function\npointer to the generated code. When Blink is generating paths, it is\ncareful to ensure that all the guest instructions which are added to a\npath, only exist within the confines of a single 4096-byte page. Thus\nwhen a page needs to be invalidated, Blink simply deletes any hook for\neach address within the page.\n\nWhen RWX memory is used, Blink can't rely on mprotect() to communicate\nthe intent of the guest program. What Blink will do instead is protect\nany RWX guest memory, so that it's registered as read-only in the host\noperating system. This way, whenever the guest writes to RWX memory, a\nSIGSEGV signal will be delivered to Blink, which then re-enables write\npermissions on the impacted RWX page, flips a bit to the thread in the\nSMC state and then permits execution to resume for at least one opcode\nbefore the interpreter loop notices the SMC state, invalidates the JIT\nand re-enables the memory protection. This means that:\n\n1. Memory ops in general aren't slowed down by Blink's SMC support\n2. RWX memory can be written-to with some overhead\n3. RWX memory can be read-from with zero overhead\n4. Changes take effect when a JIT path ends\n\nIntel's sixteen thousand page manual lays out the following guidelines\nfor conformant self-modifying code:\n\n> To write self-modifying code and ensure that it is compliant with\n> current and future versions of the IA-32 architectures, use one of\n> the following coding options:\n>\n> (* OPTION 1 *)  \n> Store modified code (as data) into code segment;  \n> Jump to new code or an intermediate location;  \n> Execute new code;\n>\n> (* OPTION 2 *)  \n> Store modified code (as data) into code segment;  \n> Execute a serializing instruction; (* For example, CPUID instruction *)  \n> Execute new code;\n>\n> ──Quoth Intel Manual V.3, §8.1.3\n\nBlink implements this behavior because branching instructions cause JIT\npaths to end, paths only jump into one another selectively , and lastly\nserializing instructions are never added to paths in the first place.\n\nIntel's rules allow Blink some leeway to make writing to RWX memory go\nfast, without causing any signal storms, or incurring too much system\ncall overhead. As an example, consider the internal statistics printed\nby the [`smc2_test.c`](test\u002Ffunc\u002Fsmc2_test.c) program:\n\n```\nmake -j8 o\u002F\u002Fblink\u002Fblink o\u002F\u002Ftest\u002Ffunc\u002Fsmc2_test.elf\no\u002F\u002Fblink\u002Fblink -Z o\u002F\u002Ftest\u002Ffunc\u002Fsmc2_test.elf\n[...]\nicache_resets                    = 1\njit_blocks                       = 1\njit_hooks_installed              = 132\njit_hooks_deleted                = 19\njit_page_resets                  = 21\nsmc_checks                       = 22\nsmc_flushes                      = 22\nsmc_enqueued                     = 22\nsmc_segfaults                    = 22\n[...]\n```\n\nThe above program performs 300+ independent write operations to RWX\nmemory. However we can see very few of them resulted in segfaults, since\nmost of those ops happened in the SlowMemCpy() function which uses a\ntight conditional branch loop rather than a proper jump. This let the\nprogram get more accomplished, before dropping out of JIT code back into\nthe main interpreter loop, which is where Blink checks the SMC state in\norder to flush the caches reapply any missing write protection.\n\n## Pseudoteletypewriter\n\nBlink has an xterm-compatible ANSI pseudoteletypewriter display\nimplementation which allows Blink's TUI interface to host other TUI\nprograms, within an embedded terminal display. For example, it's\npossible to use Antirez's Kilo text editor inside Blink's TUI. For the\ncomplete list of ANSI sequences which are supported, please refer to\n[blink\u002Fpty.c](blink\u002Fpty.c).\n\nIn real mode, Blink's PTY can be configured via `INT $0x16` to convert\nCGA memory stored at address `0xb0000` into UNICODE block characters,\nthereby making retro video gaming in the terminal possible.\n\n## Real Mode\n\nBlink supports 16-bit BIOS programs, such as SectorLISP. To boot real\nmode programs in Blink, the `blinkenlights -r` flag may be passed, which\nputs the virtual machine in i8086 mode. Currently only a limited set of\nBIOS APIs are available. For example, Blink supports IBM PC Serial UART,\nCGA, and MDA. We hope to expand our real mode support in the near\nfuture, in order to run operating systems like ELKS.\n\nBlink supports troubleshooting operating system bootloaders. Blink was\ndesigned for Cosmopolitan Libc, which embeds an operating system in each\nbinary it compiles. Blink has helped us debug our bare metal support,\nsince Blink is capable of running in the 16-bit, 32-bit, and 64-bit\nmodes a bootloader requires at various stages. In order to do that, we\nneeded to implement some ring0 hardware instructions. Blink has enough\nto support Cosmopolitan, but it'll take much more time to get Blink to a\npoint where it can boot something like Windows.\n\n## Executable Formats\n\nBlink supports several different executable formats. You can run:\n\n- x86-64-linux ELF executables (both static and dynamic).\n\n- Actually Portable Executables, which have either the `MZqFpD` or\n  `jartsr` magic.\n\n- Flat executables, which must end with the file extension `.bin`. In\n  this case, you can make executables as small as 10 bytes in size,\n  since they're treated as raw x86-64 code. Blink always loads flat\n  executables to the address `0x400000` and automatically appends 16mb\n  of BSS memory.\n\n- Real mode executables, which are loaded to the address `0x7c00`. These\n  programs must be run using the `blinkenlights` command with the `-r`\n  flag.\n\n## Filesystems\n\nWhen Blink is built with the VFS feature enabled (`--enable-vfs`),\nit comes with three default filesystems:\n- `hostfs`: A filesystem that mirrors a certain directory on the\nhost's filesystem. Files on `hostfs` mounts have everything\nread from and written directly to the corresponding host directory,\nwith the exception of `st_dev` and `st_ino` fields. `st_dev` is\nmanaged by Blink's VFS subsystem, while `st_ino` is calculated using\na hash function based on the host's `st_dev` and `st_ino` value.\n- `proc`: A filesystem that emulates Linux's `\u002Fproc` using information\navailable to Blink.\n- `devfs`: A filesystem that emulates Linux's `\u002Fdev`. Currently, this\nis only a wrapper for `hostfs`.\n\nWhen Blink is launched, these default mount points are added:\n- `\u002F` of type `hostfs` pointing to the corresponding host directory.\nThis is determined by querying `$BLINK_PREFIX` and the `-C` parameter\nin order and falls back to `\u002F` if neither are available.\n- `\u002Fproc` of type `proc`.\n- `\u002Fdev` of type `devfs`.\n- `\u002FSytemRoot` of type `hostfs` pointing to the host's root `\u002F`.\n\nIt is possbile for programs to add additional mount points by using\nthe `mount` syscall (for `hostfs` mounts, pass the path to the\ndirectory on the _host_ as the `source` argument), but see the quirks\nbelow.\n\n## Quirks\n\nHere's the current list of Blink's known quirks and tradeoffs.\n\n### Flags\n\nFlag dependencies may not carry across function call boundaries under\nlong mode. This is because when Blink's JIT is speculating whether or\nnot it's necessary for an arithmetic instruction to compute flags, it\nconsiders `RET` and `CALL` terminal ops that break the chain. As such\n64-bit code shouldn't do things we did in the DOS days, such as using\ncarry flag as a return value to indicate error. This should work fine\nwhen `STC` is used to set the carry flag, but if the code computes it\ncleverly using instructions like `SUB`, then EFLAGS might not change.\n\nAs a special case, if a `RET` instruction sports a `REP` prefix, then\nBlink can return flags across the `RET`.\n\n### Faults\n\nBlink may not report the precise program counter where a fault occurred\nin `ucontext_t::uc_mcontext::rip` when signalling a segmentation fault.\nThis is currently only possible when `PUSH` or `POP` access bad memory.\nThat's because Blink's JIT tries to avoid updating `Machine::ip` on ops\nit considers \"pure\" such as those that only access registers, which for\nreasons of performance is defined to include pushing and popping.\n\n### Threads\n\nBlink doesn't have a working implementation of `set_robust_list()` yet,\nwhich means robust mutexes might not get unlocked if a process crashes.\n\n### Coherency\n\nPOSIX.1 provides almost no guarantees of coherency, synchronization, and\ndurability when it comes to `MAP_SHARED` mappings and recommends that\nmsync() be explicitly used to synchronize memory with file contents. The\nLinux Kernel implements shared memory so well, that this is rarely\nnecessary. However some platforms like OpenBSD lack write coherency.\nThis means if you change a shared writable memory map and then call\npread() on the associated file region, you might get stale data. Blink\nisn't able to polyfill incoherent platforms to be as coherent as Linux,\ntherefore apps that run in Blink should assume the POSIX rules apply.\n\n### Signal Handling\n\nBlink uses `SIGSYS` to deliver signals internally. This signal is\nprecious to Blink. It's currently not possible for guest applications to\ncapture it from external processes.\n\n### Memory Protection\n\nBlink offers guest programs a 48-bit virtual address space with a\n4096-byte page size. When programs are run on (1) host systems that have\na larger page (e.g. Apple M1, Cygwin), and (2) the linear memory\noptimization is enabled (i.e. you're *not* using `blink -m`) then Blink\nmay need to relax memory protections in cases where the memory intervals\ndefined by the guest aren't aligned to the host system page size. This\nmeans that, on system with a larger than 4096 byte page size:\n\n1. Misaligned read-only pages could become writable\n2. JIT hooks might not invalidate automatically on misaligned RWX pages\n\nIt's recommended, when calling functions like mmap() and mprotect(),\nthat both `addr` and `addr + size` be aliged to the host page size.\nBlink reports that value to the guest program in `getauxval(AT_PAGESZ)`,\nwhich should be obtainable via the POSIX API `sysconf(_SC_PAGESIZE)` if\nthe C library is implemented correctly. Please note that when Blink is\nrunning in full virtualization mode (i.e. `blink -m`) this concern no\nlonger applies. That's because Blink will allocate a full system page\nfor every 4096 byte page that's mapped from a file.\n\n### Process Management\n\nFor builds with the VFS feature enabled (--enable-vfs), while a `procfs`\nmount is available at `\u002Fproc`, it is limited to information available\nin a single process. Only `\u002Fproc\u002Fself` and the corresponding PID folder\nis available. This means programs can get the expected values at\n`\u002Fproc\u002Fself\u002Fexe` and similar files, but process management tools like\n`ps` will not work.\n\nOn Linux, some `procfs` symlinks possess a hardlink-like ability of\nbeing dereferenceable even after the target has been `unlink`ed.\nBlink's implementation currently does not support this use case.\n\n### Mounts\n\nFor builds with the VFS feature enabled (`--enable-vfs`), Blink does not\nshare mount information with other emulated processes. As a result,\ncommands like this may seem to work (by return a 0 status code):\n\n```sh\nmount -t hostfs \u002Fsome\u002Fpath\u002Fon\u002Fhost folder\n```\n\nBut subsequent calls to `ls folder` on the same shell still does not\ndisplay the expected contents. This is because the `mount` command\ncould only modify the mount table kept by itself (and propagated to\nchildren through `fork`), but not the one used by its parent shell.\nIn other words, Blink behaves as if `CLONE_NEWNS` is added to every\n`clone` call, separating the mount namespace of the child from its\nparent.\n\nSome might view this behavior as a feature, but it diverges from\nclassic system behavior; a mechanism for handling shared process\nstate is being considered in\n[#92](https:\u002F\u002Fgithub.com\u002Fjart\u002Fblink\u002Fissues\u002F92).\n","Blink 是一个极小的 x86-64-linux 模拟器，能够在不同操作系统和硬件架构上运行 x86-64-linux 程序。其核心功能包括支持在任何 POSIX 系统上执行 Linux 二进制文件，且体积仅有 221KB（关闭可选功能后为 115KB），比 QEMU 更加轻量。此外，Blink 在某些基准测试中速度是 QEMU 的两倍，并且特别适合运行编译器等临时程序。配套的调试工具 Blinkenlights 提供了图形化的程序执行可视化界面，支持反向调试等功能。该项目适用于需要跨平台运行或调试 x86-64-linux 应用的开发者，尤其是在资源受限的环境中。",2,"2026-06-11 03:06:35","top_language"]