{"id":13836081,"url":"https://github.com/ghaerr/blink16","last_synced_at":"2025-05-16T03:33:23.462Z","repository":{"id":94013075,"uuid":"603283244","full_name":"ghaerr/blink16","owner":"ghaerr","description":"Tiny visual 8086 emulator based on Blink","archived":false,"fork":false,"pushed_at":"2023-04-26T17:27:07.000Z","size":10047,"stargazers_count":57,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"blink16","last_synced_at":"2024-02-17T06:34:41.808Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ghaerr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":["jart"]}},"created_at":"2023-02-18T03:06:57.000Z","updated_at":"2024-02-06T08:26:46.000Z","dependencies_parsed_at":"2024-01-13T16:44:58.984Z","dependency_job_id":"80af6709-15a1-4d69-a2ac-8aa9a3a29ce2","html_url":"https://github.com/ghaerr/blink16","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaerr%2Fblink16","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaerr%2Fblink16/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaerr%2Fblink16/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghaerr%2Fblink16/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ghaerr","download_url":"https://codeload.github.com/ghaerr/blink16/tar.gz/refs/heads/blink16","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225403628,"owners_count":17469000,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T15:00:34.971Z","updated_at":"2024-11-19T18:21:05.897Z","avatar_url":"https://github.com/ghaerr.png","language":"C","funding_links":["https://github.com/sponsors/jart"],"categories":["C"],"sub_categories":[],"readme":"# Blink16\n\nThis is an 8086 real mode only branch of [Blink](https://github.com/jart/blink), useful\nfor emulating [ELKS](https://github.com/jbruchon/elks) and MSDOS\nexecutable programs. This is an early work in progress, with\nBlink's x86_64 VM replaced with a tiny\n[8086 emulator and disassembler](https://github.com/ghaerr/86sim).\nThe system calls are also replaced for ELKS and DOS support,\nwith currently just a few syscalls implemented.\n\nThe Blink16 branch is implemented in the blink16/ directory, using portions\nof Blink from the original blink/ directory and master branch.\n\nTo build:\n```\ncd blink16\nmake\n```\n\nTo run sample binaries:\n```\ncd blink16\n./blink16 banner ELKS   # ELKS binary\n./blink16 test.exe      # DOS binary\n```\n\nTo demo booting a prebuilt ELKS kernel from 0:7c00 (use s/s/c/^C/C/C/D to step through, and mousewheel on disassembly to show execution history):\n```\nmake elks\n```\n\nScreenshot of Blink16 running 'banner':\n![Screenshot of Blink16 running banner](blink16/blink16-banner.png)\n\nA big thank you to [@jart](https://github.com/jart) for the wonderful Blink Project!!\n\nScreenshot of Blink running GCC 9.4.0:\n![Screenshot of Blink running GCC 9.4.0](blink/blink-gcc.png)\n\n[![Test Status](https://github.com/jart/blink/actions/workflows/build.yml/badge.svg)](https://github.com/jart/blink/actions/workflows/build.yml)\n[![Cygwin Test Status](https://github.com/jart/blink/actions/workflows/cygwin.yml/badge.svg)](https://github.com/jart/blink/actions/workflows/cygwin.yml)\n[![Emscripten Test Status](https://github.com/jart/blink/actions/workflows/emscripten.yml/badge.svg)](https://github.com/jart/blink/actions/workflows/emscripten.yml)\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 (a) rather than\nbeing a 4mb binary, Blink only has a ~177kb footprint; and (b) Blink\ngoes 2x faster than Qemu on some benchmarks such as emulating GCC. The\ntradeoff is Blink doesn't have as many features as Qemu. Blink is a\ngreat fit when you want a virtual machine that's extremely small and\nruns ephemeral programs much faster. For further details on the\nmotivations for this tool, please read \u003chttps://justine.lol/ape.html\u003e.\n\n[`blinkenlights`](https://justine.lol/blinkenlights) is a TUI interface\nthat may be used for debugging x86_64-linux programs across platforms.\nUnlike GDB, Blinkenlights focuses on visualizing program execution. It\nuses UNICODE IBM Code Page 437 characters to display binary memory\npanels, which change as you step through your program's assembly code.\nThese memory panels may be scrolled and zoomed using your mouse wheel.\nBlinkenlights also permits reverse debugging, where scroll wheeling over\nthe assembly display allows the rewinding of execution 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- NetBSD\n- Cygwin (no JIT on Windows yet)\n\nBlink depends on the following libraries:\n\n- libc (POSIX.1-2017)\n\nBlink can be compiled on UNIX systems that have:\n\n- A C11 compiler (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$ make -j4\n$ o//blink/blink -h\nUsage: o//blink/blink [-hjms] PROG [ARGS...]\n  -h        help\n  -j        disable jit\n  -0        to specify argv[0]\n  -m        enable memory safety\n  -s        print statistics on exit\n```\n\nHere's how you can run a simple hello world program with Blink:\n\n```sh\no//blink/blink third_party/cosmo/tinyhello.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\no//blink/blinkenlights third_party/cosmo/tinyhello.elf\n```\n\n### Testing\n\nBlink is tested primarily using precompiled x86 binaries, which are\ndownloaded automatically. You can check how well Blink works on your\nlocal 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### Alternative Builds\n\nFor maximum performance, use `MODE=rel` or `MODE=opt`. Please note the\nrelease mode builds will remove all the logging and assertion statements\nand Blink isn't mature enough for that yet. So extra caution is advised.\n\n```sh\nmake MODE=rel\no/rel/blink/blink -h\n```\n\nFor maximum tinyness, use `MODE=tiny`. This build mode will not only\nremove logging and assertion statements, but also reduce performance in\nfavor of smaller binary size whenever possible.\n\n```sh\nmake MODE=tiny\nstrip o/tiny/blink/blink\nls -hal o/tiny/blink/blink\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\n## Compiling and Running Programs under Blink\n\nBlink can be picky about which Linux executables it'll execute. For\nexample the host system page size may cause problems on non-Linux\nplatforms like Apple M1 (16kb) and Cygwin (64kb). On such platforms, you\nmay encounter an error like this:\n\n```\nI2023-01-06T18:12:51.007788:blink/loader.c:91:47550 p_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#!/bin/sh\nexec cc \\\n  -g \\\n  -Os \\\n  -no-pie \\\n  -fno-pie \\\n  -static \\\n  \"$@\" \\\n  -U_FORTIFY_SOURCE \\\n  -fno-stack-protector \\\n  -fno-omit-frame-pointer \\\n  -mno-omit-leaf-frame-pointer \\\n  -Wl,-z,common-page-size=65536 \\\n  -Wl,-z,max-page-size=65536\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/tool/scripts/cosmocc](https://github.com/jart/cosmopolitan/blob/master/tool/scripts/cosmocc)\n- [cosmopolitan/tool/scripts/cosmoc++](https://github.com/jart/cosmopolitan/blob/master/tool/scripts/cosmoc%2B%2B)\n\nIf you're not a C / 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://github.com/jart/cosmopolitan/\ncd cosmopolitan\nmake -j8 o//third_party/python/python.com\nblinkenlights -jm o//third_party/python/python.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\nSome other programs you can try, are SQLite and Antirez's Kilo editor.\n\n```\ngit clone https://github.com/jart/cosmopolitan/\ncd cosmopolitan\nmake -j8 o//third_party/sqlite3/sqlite3.com\nblinkenlights -jm o//third_party/sqlite3/sqlite3.com\nmake -j8 o//examples/kilo.com\nblinkenlights -jm o//examples/kilo.com\n```\n\nFor further details, please read [Getting Started with Cosmopolitan\nLibc](https://jeskin.net/blog/getting-started-with-cosmopolitan-libc/)\nwhich is a blog post explaining how you can write your own programs in\nthe cosmopolitan mono-repo, which naturally will be guaranteed to work\nreally well under Blink and Blinkenlights.\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 130+ Linux system call ABIs, including\nfork() and clone(). Linux system calls may only be used by long mode\nprograms via the `SYSCALL` instruction, as it is written in the System V\nABI.\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://www.jpl.nasa.gov/edu/news/2016/3/16/how-many-decimals-of-pi-do-we-really-need/)\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 `blink 4.0` in the `uname()` system call.\nPrograms may detect they're running in Blink by issuing a `CPUID`\ninstruction where `EAX` is set to the leaf number:\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 `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 `o//blink/blink -j` flag may be\npassed to disable Blink's JIT. Please note that disabling JIT makes\nBlink go 10x slower. With the `o//blink/blinkenlights` command, the `-j`\nflag takes on the opposite meaning, where it instead *enables* JIT. This\ncan be useful for troubleshooting the JIT, because the TUI display has a\nfeature that lets JIT path formation be visualized. Blink currently only\nenables the JIT for programs running in long mode (64-bit) but we may\nsupport JITing 16-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## 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/pty.c](blink/pty.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 `o//blink/blinkenlights -r` flag may be\npassed, which puts the virtual machine in i8086 mode. Currently only a\nlimited set of BIOS APIs are available. For example, Blink supports IBM\nPC Serial UART, CGA, and MDA. We hope to expand our real mode support in\nthe near future, 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## 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\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### Futexes\n\nIf futexes are shared between multiple processes then they'll have\npoorer latency, because Blink currently only supports true condition\nvariables between threads. However such code won't deadlock, since the\nPOSIX threads API requires that Blink periodically poll the futex. Blink\nalso currently doesn't unlock robust mutexes on process death. We're\nworking on both these problems.\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\nBlink's JIT currently doesn't have true asynchronous signal delivery.\nRight now Blink only checks for signals from its main interpreter loop.\nUnder normal circumstances, Blink will drop back into the main\ninterpreter loop occasionally, when returning from functions or\nexecuting system calls. However JIT'd code like the following:\n\n```c\nfor (;;) {\n}\n```\n\nCan form a cycle in the JIT graph that prevents signal delivery and can\neven deadlock shutdown. This is something we plan to fix soon.\n\n### Self Modifying Code\n\nBlink supports self-modifying code, with some caveats.\n\nBlink currently only JITs the memory intervals declared by your ELF\nprogram headers as `PF_X`. If the code stored at these addresses is\nmodified, then it must be invalidated by calling `mprotect(PROT_EXEC)`,\nwhich will atomically reset all JIT hooks if it overlaps an executable\nsection. While this takes away some of the flexibility that's normally\noffered by the x86 architecture, the fact is that operating systems like\nOpenBSD already took that capability away. So in many respects, Blink is\nhelping your code to be more portable. It's recommended that executables\nonly morph themselves a few times during their lifecycle, because doing\nso leaks JIT memory. Blink sets aside only 31mb of .bss memory for JIT.\nRunning out of JIT memory is harmless and causes Blink to safely fall\nback into interpreter mode.\n\nMemory that isn't declared by an ELF program header will be interpreted\nwhen executed. Blink's interpreter mode automatically invalidates any\ninstruction caches when memory changes, so that code may modify itself\nfreely. This upholds the same guarantees as the x86 architecture.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghaerr%2Fblink16","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghaerr%2Fblink16","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghaerr%2Fblink16/lists"}