90193f983ce793f061f583d436ea9e947cfb6782
[ikiwiki.git] / docs / handbook / handbook-linuxemu-advanced.mdwn
1 \r
2 \r
3 ## 22.8 Advanced Topics \r
4 \r
5 If you are curious as to how the Linux binary compatibility works, this is the section you want to read. Most of what follows is based heavily on an email written to [FreeBSD chat mailing list](http://lists.FreeBSD.org/mailman/listinfo/freebsd-chat) by Terry Lambert `<[mailto:tlambert@primenet.com tlambert@primenet.com]>` (Message ID: `<199906020108.SAA07001@usr09.primenet.com>`).\r
6 \r
7  **Warning:** This description applies to FreeBSD, for which it was originally written. This may or may not apply to DragonFly at this point; while FreeBSD 4.x features usually translate over to DragonFly well, your mileage may vary.\r
8 \r
9 ### 22.8.1 How Does It Work? \r
10 \r
11 DragonFly has an abstraction called an ***execution class loader***. This is a wedge into the [execve(2)](http://leaf.dragonflybsd.org/cgi/web-man?command#execve&section2) system call.\r
12 \r
13 What happens is that DragonFly has a list of loaders, instead of a single loader with a fallback to the `#!` loader for running any shell interpreters or shell scripts.\r
14 \r
15 Historically, the only loader on the UNIX® platform examined the magic number (generally the first 4 or 8 bytes of the file) to see if it was a binary known to the system, and if so, invoked the binary loader.\r
16 \r
17 If it was not the binary type for the system, the [execve(2)](http://leaf.dragonflybsd.org/cgi/web-man?command#execve&section2) call returned a failure, and the shell attempted to start executing it as shell commands.\r
18 \r
19 The assumption was a default of ***whatever the current shell is***.\r
20 \r
21 Later, a hack was made for [sh(1)](http://leaf.dragonflybsd.org/cgi/web-man?command#sh&section1) to examine the first two characters, and if they were `:\n`, then it invoked the [csh(1)](http://leaf.dragonflybsd.org/cgi/web-man?command=csh&section=1) shell instead (we believe SCO first made this hack).\r
22 \r
23 What DragonFly does now is go through a list of loaders, with a generic `#!` loader that knows about interpreters as the characters which follow to the next whitespace next to last, followed by a fallback to `/bin/sh`.\r
24 \r
25 For the Linux ABI support, DragonFly sees the magic number as an ELF binary (it makes no distinction between FreeBSD, Solaris™, Linux, or any other OS which has an ELF image type, at this point).\r
26 \r
27 The ELF loader looks for a specialized ***brand***, which is a comment section in the ELF image, and which is not present on SVR4/Solaris ELF binaries.\r
28 \r
29 For Linux binaries to function, they must be ***branded*** as type `Linux` from [brandelf(1)](http://leaf.dragonflybsd.org/cgi/web-man?command#brandelf&section1):\r
30 \r
31     \r
32     # brandelf -t Linux file\r
33 \r
34 \r
35 When this is done, the ELF loader will see the `Linux` brand on the file.\r
36 \r
37 When the ELF loader sees the `Linux` brand, the loader replaces a pointer in the `proc` structure. All system calls are indexed through this pointer (in a traditional UNIX system, this would be the `sysent[]` structure array, containing the system calls). In addition, the process is flagged for special handling of the trap vector for the signal trampoline code, and several other (minor) fix-ups that are handled by the Linux kernel module.\r
38 \r
39 The Linux system call vector contains, among other things, a list of `sysent[]` entries whose addresses reside in the kernel module.\r
40 \r
41 When a system call is called by the Linux binary, the trap code dereferences the system call function pointer off the `proc` structure, and gets the Linux, not the DragonFly, system call entry points.\r
42 \r
43 In addition, the Linux mode dynamically ***reroots*** lookups; this is, in effect, what the `union` option to file system mounts (***not*** the `unionfs` file system type!) does. First, an attempt is made to lookup the file in the `/compat/linux/`***original-path****** directory, ***then*** only if that fails, the lookup is done in the `/`***original-path****** directory. This makes sure that binaries that require other binaries can run (e.g., the Linux toolchain can all run under Linux ABI support). It also means that the Linux binaries can load and execute DragonFly binaries, if there are no corresponding Linux binaries present, and that you could place a [uname(1)](http://leaf.dragonflybsd.org/cgi/web-man?command#uname&section1) command in the `/compat/linux` directory tree to ensure that the Linux binaries could not tell they were not running on Linux.\r
44 \r
45 In effect, there is a Linux kernel in the DragonFly kernel; the various underlying functions that implement all of the services provided by the kernel are identical to both the DragonFly system call table entries, and the Linux system call table entries: file system operations, virtual memory operations, signal delivery, System V IPC, etc... The only difference is that DragonFly binaries get the DragonFly ***glue*** functions, and Linux binaries get the Linux ***glue*** functions (most older OS's only had their own ***glue*** functions: addresses of functions in a static global `sysent[]` structure array, instead of addresses of functions dereferenced off a dynamically initialized pointer in the `proc` structure of the process making the call).\r
46 \r
47 Which one is the native DragonFly ABI? It does not matter. Basically the only difference is that (currently; this could easily be changed in a future release, and probably will be after this) the DragonFly ***glue*** functions are statically linked into the kernel, and the Linux ***glue*** functions can be statically linked, or they can be accessed via a kernel module.\r
48 \r
49 Yeah, but is this really emulation? No. It is an ABI implementation, not an emulation. There is no emulator (or simulator, to cut off the next question) involved.\r
50 \r
51 So why is it sometimes called ***Linux emulation***? To make it hard to sell DragonFly! Really, it is because the historical implementation was done at a time when there was really no word other than that to describe what was going on; saying that FreeBSD [(1)](#FTN.AEN29365) ran Linux binaries was not true, if you did not compile the code in or load a module, and there needed to be a word to describe what was being loaded--hence ***the Linux emulator***.\r
52 \r
53 #### Notes \r
54 \r
55 [[!table  data="""
56 |<tablestyle="width:100%"> [linuxemu-advanced.html#AEN29365 (1)] | FreeBSD's original Linux compatibility code was committed in June 1995. It fulfilled milestone number one: running DOOM. |\r
57 """]]\r
58 \r
59 \r
60 CategoryHandbook\r
61 CategoryHandbook-linuxcompatibility\r