The FreeBSD-​linuxulator ex­plained (for de­velopers): ba­sics

The last post about the Linuxu­lat­or where I ex­plained the Linuxu­lat­or from an user point of view got some good amount of at­ten­tion. Triggered by a re­cent ex­plan­a­tion of the Linuxu­lat­or er­rno stuff to a fel­low FreeBSD de­veloper I de­cided so see if more de­velopers are in­ter­ested in some more in­fo too…

The sy­scall vec­tor

In sys/​linux/linux_sysvec.c is all the ba­sic setup to handle Linux “sys­tem stuff” in FreeBSD. The “sys­tem stuff” is about trans­lat­ing FreeBSD er­rnos to Linux er­rnos, about trans­lat­ing FreeBSD sig­nals to Linux sig­nales, about hand­ling Linux traps, and about set­ting up the FreeBSD sys­tem vec­tor (the ker­nel struc­ture which con­tains all the data to identi­fy when a Linux pro­gram is called and to be able to look­up the right ker­nel func­tions for e.g. sy­scalls and ioctls).

There is not only one sy­scall vec­tor, there is one for a.out (struct sysentvec linux_​sysvec) and one for ELF (struct sysentvec elf_​linux_​sysvec) bin­ar­ies (at least on i386, for oth­er ar­chi­tec­tures it may not make sense to have the a.out stuff, as they may­be nev­er seen any a.out Linux bin­ary).

The ELF AUX args

When an ELF im­age is ex­ecuted, the Linuxu­lat­or adds some runtime in­form­a­tion (like pages­ize, uid, guid, …) so that the user­land can query this in­form­a­tion which is not stat­ic at build-​time eas­ily. This is handled in the elf_​linux_​fixup func­tion(). If you see some er­ror mes­sages about miss­ing ELF notes from e.g. glibc, this is the place to add this in­form­a­tion to. It would not be bad from time to time to have a look what Linux is provid­ing and miss­ing pieces there. FreeBSD does not has an auto­mated way of do­ing this, and I am not aware of someone who reg­u­larly checks this. There is a little bit more in­fo about ELF notes avail­able in a mes­sage to one of the FreeBSD mail­ing lists, it also has an ex­ample how to read out this data.


Linux and FreeBSD do not share the same point of view how a trap shall be handled (SIGBUS or SIGSEGV), the cor­res­pond­ing de­cision mak­ing is handled in translate_​traps() and a trans­la­tion table is avail­able as _​bsd_​to_​linux_​trapcode.


The val­ues for the sig­nal names are not the same in FreeBSD and Linux. The trans­la­tion tables are called linux_​to_​bsd_​signal and bsd_​to_​linux_​signal. The trans­la­tion is a fea­ture of the sy­scall vec­tor (= auto­mat­ic).


The val­ues for the er­rno names are not the same in FreeBSD and Linux. The trans­la­tion table is called bsd_​to_​linux_​errno. Re­turn­ing an er­rno in one of the Linux sy­scalls will trig­ger an auto­mat­ic trans­la­tion from the FreeBSD er­rno value to the Linux er­rno value. This means that FreeBSD er­rnos have to be re­turned (e.g. FreeBSD ENOSYS=78) and the Linux pro­gram will re­ceive the Linux value (e.g. Linux ENOSYS=38, and as the Linux ker­nel re­turns neg­at­ive er­rnos, the linux pro­gram will get –38).

If you see some­where an “-ESOMETHING” in the Linuxu­lat­or code, this is either a bug, or some clever/​tricky/​dangerous use of the sign-​bit to en­code some in­fo (e.g. in the fu­tex code there is a func­tion which re­turns –ENOSYS, but the sign-​bit is used as an er­ror in­dic­at­or and the call­ing code is re­spons­ible to trans­late neg­at­ive er­rnos in­to pos­it­ive ones).


The Linux sy­scalls are defined sim­il­ar to the FreeBSD ones. There is a map­ping table (sys/linux/syscalls.master) between sy­scall num­bers and the cor­res­pond­ing func­tions. This table is used to gen­er­ate code (“make sysent” in sys/​/​linux/​) which does what is ne­ces­sary.