Subject: Re: Per-process personalities in emulations
To: Niklas Hallqvist <niklas@appli.se>
From: Frank van der Linden <frank@fwi.uva.nl>
List: tech-kern
Date: 11/10/1995 13:22:55
Quoting Niklas Hallqvist,

> I'm doing some work on emulations in NetBSD/i386 and have come to know
> that different vendors have done small things slightly different and
> that applications have come to rely on this.

The basic problem is, that the kernel can't always figure out which
emulation to use by just looking at the binary. This happens in the situations
you describe, and also in the Linux/SVR4 case for statically linked ELF
binaries. So we need to give the kernel a hand (unfortunately, for lack
of a better solution).

The solution you suggest might be the only workable one, with some changes
perhaps. The wrapper might be extended to a more general purpose program,
say emul(1), which would look something like:

	emul [-e emultype] [-f emulflags] executable args ...

emultype is the emulation type, i.e. 'svr4', 'sunos', 'linux'
emulflags are the flags to use, like 'dellsvr4', 'ncrsvr4'

Of course, a lot of combinations for emulation types or flags don't make
sense. Also, this program should not be required, it's just there to help
the exec code make a decision and set some additional info. Then there
are some other details, like what the exec code should do with the info.
It should just take it as a hint, and if the hint and what it really finds
don't match, just return ENOEXEC. Also, if there's a hint for
an emulation type, there's no need to check the other possibilities. The
hinted type is either used if the exec code could not find out what to
do by itself, or ENOEXEC is returned.

The best (least ugly?) way to implement this would be to create an exec()
call which accept the additional flags, either as 2 additional parameters,
or as a pointer to a structure containing the emulation type and flags.

In the latter case, emul(1) would look something like:

main(argc, argv, envp)
{
	struct exec_hint eh;

	/* parse arguments */
	execvee(&eh, name, new_argv, envp);
}

Again, adding some args to the execve() syscall (i.e. giving it a new number,
add the args, and keep the old one for compat reasons) isn't really a nice
way to solve things, but I can't see a better way to fix this. I like the
scheme better than a seperate call, but I'm hoping something better is
possible.

One last related issue: currently a check on a process being of a certain
emulation type is done by comparing p->p_emul to the address of one of
the available, constant, emul structs. However, this struct contains mostly
info that is needed only during exec, it is not needed anymore when the
program is running. This leads to the situation that if you want to check
whether a process is running under Linux emulation, you have to check both
&emul_linux_aout and &emul_linux_elf, although at runtime they behave
exactly the same. The information needed at load time needs to be decoupled
from the information needed at runtime.

- Frank