Linux ELF Compatibility
What is it?
The Linux compatibility layer will let statically linked Linux x86-64 programs such as busybox and musl builds run unmodified on Impossible OS, in the kernel and without a virtual machine: "WSL in reverse". It needs a Linux system call table, path translation from /home and /tmp to Windows paths, a per-process integer file descriptor table, and signals. None of its eleven sections has shipped. The kernel already loads ELF programs and builds a Linux-style start-up stack for them, but those programs use Impossible OS's own system calls, not Linux's.
How does it work?
Today.
- ELF loading.
elf_load()validates an ELF64 x86-64 image and maps itsPT_LOADsegments (elf.h,elf.c). It is one of three formatsexec_init()registers, beside EIF and PE, and the loader is picked by magic bytes; the registry is sealed at the end ofexec_init(), so a new loader cannot be added at run time (exec.c). - SYSV start-up stack. Every exec already gets a Linux x86-64 style initial stack:
argc,argv, an emptyenvpand an auxiliary vector withAT_PHDR,AT_PHENT,AT_PHNUM,AT_PAGESZ,AT_ENTRY, user and group IDs of 0, 16 random bytes forAT_RANDOMand CPU feature bits inAT_HWCAP(task.c). The roadmap's section 2 is therefore partly done, in the generic exec path rather than a compat module. - System calls.
INT 0x80is wired (VECTOR_LINUX_SYSCALLinvectors.h), but it dispatches Impossible OS's own numbering:SYS_WRITEis 1,SYS_READis 2 andSYS_EXITis 3 (syscall.h), where Linux hasread0 andwrite1. So "Linux-style" today means only the vector. TheSYSCALLinstruction goes somewhere else again: it dispatches into the NT service table (SSDT) and stores a Win32 error in the thread's TEB on failure (syscall_fast.c). - Signals.
signal_send(),signal_send_group()andsignal_ctrl_c()queue a signal, andSYS_SIGNAL(34) registers a handler (signal.h). Nothing callssignal_check()yet, so a pending signal is never delivered, and there are no Linuxrt_sigaction,sigreturnor user-mode signal frames.
Planned design.
flowchart LR
A[Static Linux ELF] --> B[elf_linux_load: set is_linux_elf]
B --> C[SYSCALL entry]
C -->|is_linux_elf| D[linux_syscall_dispatch: RDI RSI RDX R10 R8 R9]
C -->|native| E[Impossible OS syscalls]
D --> F[translate to native services, return -errno]
- Per-task state. An
is_linux_elfflag, a 256-entry fd table, abrkregion and 32 signal handler slots in the task. - Loader.
elf_linux_load()for static binaries only; aPT_INTERP(dynamic linker) request returnsENOEXEC. - Dispatch. The syscall entry branches on the flag before touching arguments, because Linux passes them in
RDI,RSI,RDX,R10,R8,R9. - About 30 translated calls. File I/O (
read,write,open,close,lseek,stat,fstat,getdents64), process (exit,getpid,getuid,arch_prctl,uname), memory (brk,mmap,munmap,mprotect) and a few more (ioctl,writev,clock_gettime,nanosleep,getrandom). - Paths.
/hometoC:\Users\Default,/tmptoC:\Temp,/bintoC:\Impossible\Bin, plus synthesised/proc/self/maps,/dev/nulland/dev/urandom. - Files, directories and signals. fd
dupanddup2with standard streams pre-opened,opendirandgetcwd, andrt_sigactionwithSIGINT,SIGCHLD,SIGKILLandSIGTERM. - Shell and tests. A
[Linux]tag in the process list, then a static hello world and busybox (ls,cat,echo,grep,sh).
What are its interfaces?
| Interface | Status |
|---|---|
elf_load(), exec_load_fmt(), SYSV initial stack and auxv |
Shipped |
INT 0x80 (native SYS_* numbers) and SYSCALL (NT services) entry |
Shipped |
signal_send(), signal_ctrl_c(), SYS_SIGNAL |
Shipped; delivery not wired |
elf_linux_load(), linux_syscall_dispatch(), linux_syscall_table[] |
Planned |
linux_path_to_win32(), Linux fd table, rt_sigaction |
Planned |
How do I use it?
Nothing Linux-specific can run yet: a real Linux binary would issue Linux system call numbers that the kernel reads as its own. The ELF path itself is used by every program on the system disk, and make test-exec covers magic routing and ELF segment validation.
What is not implemented yet?
- Linux Flags and FD Table and the ELF Linux Loader (the stack and auxv part already runs for every exec)
- Syscall Entry Dispatch and the Linux Syscall Translation Table
- Path Translation, the Linux File Descriptor Table and POSIX Filesystem Stubs
- Signal Stubs, which also need the native signal delivery owned by the process model roadmap
- Shell ELF Integration and the busybox test
- Dynamic ELF, a stretch goal
How does it compare with Windows 11 and Linux?
Windows 11 runs Linux programs through WSL 2, a real Linux kernel in a lightweight virtual machine with its own disk image; the original WSL 1 translated system calls in the kernel much as this plan does. Linux runs its own binaries natively. The Impossible OS plan is WSL 1 in shape: static ELF binaries share the scheduler, memory manager and file system with Win32 programs, with no hypervisor and no separate disk. Dynamic linking is left to a later stretch.
See also
- Linux ELF Compatibility Layer roadmap
- Binary Format System
- Process Model Extensions
- Exception Dispatch and SEH, whose fault-to-signal step waits on this roadmap
- Win32 PE Loader