*** Why are multiple personalities necessary?

Personalities are used to provide the expected set of syscalls and error
code mapping for non-Linux processes. In theory the set of syscalls and
error codes should be standardised across all SYSV systems. In practice
this is the case for SVR4, however SVR3 is a much older code base and
many vendors have extended it leading to incompatibilities between the
expected interfaces. Personalities allow us to vary the interface presented
on a per-process basis thus allowing Linux to run binaries created for
different vendor's extended SVR3s simultaneously.


*** How are personalities implemented?

The per-process task structure contains a field "personality". This defaults
to 0 for Linux binaries, 1 (SVR4) for ELF binaries and 2 (SVR3) for COFF
binaries. However when the COFF loader is called on to load a new binary
it looks at the first 1k of data in each .comment section and compares
the strings it finds with a built in table. If it finds a match it will
set the personality appropriately.

  When the application makes a system call the iBCS emulation layer uses
the personality code in the per-process task structure to determine which
system call mappings to use to locate the correct function.

  If the function returns an (Linux) error code the iBCS emulation layer
uses the personality code to determine which error code mappings to use
to translate the error code in to a value the application will understand.


*** What personalities are implemented?

Currently the implemented personalities are SVR4, SVR3 (as a direct
subset of SVR4), SCO 3.[24] and Wyse V/386 3.2.1. Of these the Wyse
emulation is the most complete at this time. Rather than using the
more common streams based TCP/IP stack on their SVR3, Wyse used a BSD
implementation with a system call interface. Currently the Wyse emulation
is the only one capable of running non-Linux TCP/IP binaries.


*** When do I need to add a personality rather than use the default?

When your applications start failing for inexplicable reasons! Seriously,
if you have an SVR3 based Unix which does not currently have its own
personality defined then you should check some things very carefully.

  Firstly compare your system's /usr/include/sys/errno.h with the data
in the Error.map file. If the values defined in your errno.h do not
match those in the ABI column then you will need to create a new
personality in order to map error codes to the correct values.

  Next compare your system's /usr/include/sys.s with the data in the
Syscall.map file. If there are system calls in your sys.s that don't
do the same thing as those in the ABI column (other than ones that
simply aren't implemented on your system) then you will need to create
a new personality in order to mapp system calls to the correct functions.


*** How do I add a new personality?

The first step is to find a way for the COFF loader to recognise your
binaries as being different. To do this you need to examine the comments
embedded in a range of binaries, system executables, bought programs of
various ages and locally compiled programs, using "mcs -p" to list the
.comments sections. If you don't have "mcs" use "strings" and look for
version or copyright messages. You are looking for one or more strings
near the top which uniquely identify the system.

  Once you have your identifying strings you must add a value for the
new personality to linux/include/linux/personality.h (just use the
next highest number) and add the strings to the table in the COFF loader
linux/fs/binfmt_coff.c.

  The next step is to modify the error map. Edit the file errmap.inc and
look at the end of the file where there is an array of pointers to error
maps call err_map. There is one entry for each personality. Add a new
entry to the end for your personality. If your personality is compatible
with an exising personality you can simply reuse the same error map (see
the duplicate entries for the SVR4 map which is use for both SVR4 and
SVR3 personalities), otherwise you must figure out how to create a new
error mapping. One day it may be documented here :-).

  Next you must modify the syscall mapping. Edit the file callmap.inc
and look at the end of the file where there is an array containg one
pointer for each personality. Add a new entry to the end. If your syscalls
match one of the existing personalities you may reuse the existing map.
Otherwise you have to build a new one. Again, one day it may be documented
here...
