Since the ELF format provides no way to tell the difference between FreeBSD,
SysV, and Linux ELF binaries, we need to devise a way to set the correct
compatibility sysvec for ELF binaries. Dynamic bins work fine, but static
ELF binaries are always assumed to be FreeBSD (therefore Linux ELF binaries do
not work in -current).
I've heard / thought of 3 possible fixes:
1. Use a wrapper program that will pass in the sysvec to use when running a
binary. I.E. you'd need to invoke a static ELF binary with something like
"compat -linux linux.helloworld.elf.static". This is pretty messy IMO.
2. Use one of the unused bytes in the ELF e_ident to store an "OS Type".
The problem with this is that you'd need to alter a Linux ELF binary to add
the "OS Type". While this wouldn't break anything, it's very messy.
3. Follow the "interp" sections hints (current behavior) unless the
environment variable COMPAT_SYSVEC exists. If the variable exists, it
overrides the sysvec in the "interp" section. This means that we can now
invoke Linux ELF binaries by:
(export COMPAT_SYSVEC=linux; linux.helloworld.elf.static)
I think solution #3 would be the cleanest way to do this... The patch below
will implement this solution. It works great here.
Fix: This implements solution #3 from above. Valid values for the COMPAT_SYSVEC
environment variable are currently "freebsd" and "linux". Don't forget to
recompile the linux LKM since this edits a header file.
On Tue, 26 Mar 1996, Sujal Patel wrote:
> >Synopsis: Differentiation of FreeBSD & Linux ELF binaries [patch]
> 3. Follow the "interp" sections hints (current behavior) unless the
> environment variable COMPAT_SYSVEC exists. If the variable exists, it
> overrides the sysvec in the "interp" section. This means that we can now
> invoke Linux ELF binaries by:
> (export COMPAT_SYSVEC=linux; linux.helloworld.elf.static)
Maybe I was a bit too tired when I wrote this patch, but I don't really
think it's a good idea to let the kernel parse the environment :)
How about instead of that, add an extra argument to the execve() syscall
(to hold the emulation type requested), and then have libc pass in the
emulation type requested (by reading the COMPAT_SYSVEC environment
variable). Also, the libc exec() and friends can strip out the
COMPAT_SYSVEC environment variable, so it is not inherited by the
processes children (which is probably the desired behavior?).
This is my PR, and I'm working on a better approach for fixing this.
Fixed by sos in v1.1 of brandelf.c