ONLamp.com
oreilly.comSafari Books Online.Conferences.

advertisement


Linux Compatibility on BSD for the PPC Platform
Pages: 1, 2, 3, 4

This function performs several tests. The first test is the linux_elf32_signature(), which looks for an interpreter name specific to Linux. The interpreter is a helper program used to run the executable. This is the ld.so program used to launch dynamically linked programs. The linux_elf32_signature() looks in the ELF headers for an interpreter like /lib/ld.so or /lib/ld-linux.so, which is really Linux-specific. For instance, a NetBSD ELF program uses /usr/libexec/ld.elf_so, and a System V Release 4 system should use /usr/lib/ld.so.



This test is good for dynamically linked binaries, but it fails for statically linked binaries, for which there is no interpreter name in the ELF header. To fix this flaw, there is a second test, enabled by the LINUX_GCC_SIGNATURE macro, linux_elf32_gcc_signature(), which looks for a GCC signature in the .comment ELF section of the executable. This is not a very good test, since this GCC signature is specific to GCC but not to Linux. Anyway, for some unknown reasons, this test failed on the PowerPC.

We therefore have to find an alternative way of matching statically linked Linux binaries. The objdump(1) command is useful to investigate for such a new method: objdump -h program will dump the ELF section headers of the program, and objdump -j .name -s program will dump the content of named section .name. Here is an example of objdump -h output for a statically linked Linux binary:

$ objdump -h hello                         

hello:        file format elf32-powerpc

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00030930  018000a0  018000a0  000000a0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .init         00000080  018309d0  018309d0  000309d0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .fini         00000028  01830a50  01830a50  00030a50  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .rodata       00003f8c  01830a78  01830a78  00030a78  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 __libc_atexit 00000004  01834a04  01834a04  00034a04  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .sdata2       00000000  01834a08  01834a08  00034a08  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .data         00000cb8  01874a08  01874a08  00034a08  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  7 .got2         00000010  018756c0  018756c0  000356c0  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  8 .ctors        00000010  018756d0  018756d0  000356d0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  9 .dtors        00000008  018756e0  018756e0  000356e0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 10 .got          00000010  018756e8  018756e8  000356e8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 11 .sdata        0000011c  018756f8  018756f8  000356f8  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 12 .sbss         00000024  01875814  01875814  00035814  2**2
                  ALLOC
 13 .bss          000008b8  01875838  01875838  00035814  2**2
                  ALLOC
 14 .stab         00000cfc  00000000  00000000  00035814  2**2
                  CONTENTS, READONLY, DEBUGGING
 15 .stabstr      00000fba  00000000  00000000  00036510  2**0
                  CONTENTS, READONLY, DEBUGGING
 16 .comment      00002060  00000fba  00000fba  000374ca  2**0
                  CONTENTS, READONLY

Dumping the ELF section header, we can see that all statically linked Linux programs have a section named __libc_atexit. This is specific to Linux, and as far as we know, it does not occur on any other operating system. A good point is that this __libc_atexit section does not seems to be Linux/PowerPC specific: We can find it in Linux/i386 static binaries as well.

We therefore have to write a new test in sys/compat/linux/common/linux_exec_elf32.c, enabled by the LINUX_ATEXIT_SIGNATURE macro. This test just checks if there is a __libc_atexit section in the ELF header. With this test, statically linked Linux binaries are matched. We can check this by enabling the DEBUG_LINUX macro and looking at what the kernel outputs when we try to run the binary. With this new test, it is very likely that the hello world program now runs in compatibility.

In the event it does not work, the way of solving the problem is running ktrace(1) on the program on the NetBSD box, and the Linux equivalent (which is strace(1)) on a Linux box, and see what is going wrong. Possible issues are badly translated syscalls. For instance, if we incorrectly translated mmap() to dup2(), this shows up immediately on a kernel trace, because we see that dup2() is called instead of mmap(). We need to rebuild kdump(1) if we want it to display the system call names and arguments when running emulated binaries. Generally speaking, we need to recompile kdump(1) each time we modify any syscalls.master file.

Now that statically linked binaries work, we can try dynamically linked binaries. Note that you need to download a set of Linux libraries from a PowerPC Linux box in order to run dynamically linked programs. For the hello world program, you need at least ld.so.1 and libc.6.

On the PowerPC, dynamically linked programs were immediately matched by the linux_elf32_signature() test, but running them did not work, either because it crashed, or because we got a Linux ld.so message saying that we invoked ld.so without arguments. We will focus on these dynamic binaries-specific issues in part 2.

Emmanuel Dreyfus is a system and network administrator in Paris, France, and is currently a developer for NetBSD.


Return to ONLamp.com.





Sponsored by: