IRIX Binary Compatibility, Part 3by Emmanuel Dreyfus
IRIX Oddities: system calls that you will not see anywhere else!
Now that we are able to launch dynamic binaries, the goal is to get them linking. The dynamic linker has to do a lot of system calls before actually launching the program. Most of them are plain SVR4, and hence are taken from sys/compat/svr4. Here, we will deal with IRIX-specific system calls.
One of the very first things on which we fail when running IRIX 6.5
binaries is the
syssgi(2) system call. In fact,
syssgi(2) is more like a meta-system call. Its first argument is an
request. Depending on
syssgi(2) will run literally dozens of different commands. The remaining arguments to
syssgi(2) are interpreted according to the
syssgi(2) commands include some quite standard functionality that is
implemented in plain system calls on NetBSD, such as
getpid(2). There are also some SGI-specific things, such as commands to get hardware inventory, system configuration, or NVRAM values.
In This Series
IRIX Binary Compatibility, Part 6
IRIX Binary Compatibility, Part 5
IRIX Binary Compatibility, Part 4
IRIX Binary Compatibility, Part 2
IRIX Binary Compatibility, Part 1
The big question is why SGI decided to fold so much functionality into a single system call. There must be a good reason for doing so, but it is not easy to guess. The only thing that is obvious when you are doing some reverse engineering on
syssgi(2) is that for many requests, you do not know what arguments are used when calling
syssgi(2). The only information available is the name of the request, and it makes things much more difficult.
syssgi(2) emulation in NetBSD is done in sys/compat/irix/irix_syssgi.c:irix_sys_syssgi().
It is just a giant switch on the request value, which will branch to
various kernel functions implementing the request. All standard features, such as
getpid(2), are quite easy to implement. Others are more tricky.
The first difficulty with
syssgi(2) is the
ELFMAP request. The dynamic
syssgi(2) with this request, and all we can find in the
syssgi(2) man page is that this is an interface to implement a system
library function, and that this interface is subject to change. Not
Fortunately, Linux already tried to get there, and the person that
worked on it managed to discover that
ELFMAP takes a file descriptor, an
ELF program header array, and the array length, and then maps the
ELF sections described in the array in the calling process' user space. Information on this can be found inside Linux kernel sources, in
syssgi(ELFMAP) is a kernel implementation of a part of the
dynamic linker. Native binaries on a NetBSD system map each code section doing a
mmap(2). Here again, one could wonder what the reasons are for pushing that code from userland to the kernel. One reason could be to improve performance by saving system calls: an IRIX binary can map a library with only one system call.
Another way of guessing what the
syssgi(ELFMAP) function does is to use the
par(1) command in IRIX. This command is similar to
ktrace(1) on NetBSD: it reports the system call activity of a user program. Fortunately,
syssgi(ELFMAP) gets disassembled into a more system-call-looking presentation:
31mS : open("/lib/rld", O_RDONLY, 04) = 3 31mS : read(3, <7f 45 4c 46 01 02 01 00 00 00>..., 512) = 512 32mS : elfmap(3, 0x7fff2d98, 2) = 0xfb60000
Here is the
kdump(1) output on NetBSD for this:
1343 ftp CALL open(0xfb3509c,0,0x4) 1343 ftp NAMI "/emul/irix/lib/rld" 1343 ftp NAMI "/emul/irix" 1343 ftp NAMI "/emul/irix/lib/rld" 1343 ftp RET open 3 1343 ftp CALL read(0x3,0x7fffe76c,0x200) 1343 ftp RET read 512/0x200 1343 ftp CALL syssgi(0x44,0x3,0x7fffe7e0,0x2,0,0xfb3509c)
NB : 0x44 is the request code for
ELFMAP. This is defined in IRIX's
Here we get the confirmation that:
- We should never really trust
par(1)about what is going on, because it does masquerade on some system calls.
syssgi(ELFMAP)really expects three arguments.
- The first one is very likely to be the file descriptor just acquired
- It is much more difficult to guess what the second and third arguments are.
- We need to discover the returned value.