linuxarchitecturemipsendiannessmips64

How to distinguish between mips cpu types on linux when dpkg-architecture is absent?


Short question: how can I reliably distinguish between mips, mipsel, mips64 and mips64el on any linux distribution?

Longer explanation:

We provide statically built/distribution independent binaries (for TeX) for many architectures. Installation script usually runs uname -s and uname -m to determine operating system and architecture. Binaries are then fetched from server based on that decision, so it needs to works reliably. And it does. Almost everywhere except for Mac OS X 10.6 and Debian. Mac would report i386 on OS that runs 64-bit applications, while Debian reports mips64 for 32-bit OS.

Debian on mips64 correctly reports processor type, but that doesn't help me for at least two reasons:

  1. OS is 32-bit, not 64-bit as the name might suggest.
  2. It is running in little-endian mode. Debian calls that mipsel, not mips. It can often be switched, but OS only runs in one mode and mips software is often incompatible with mipsel.

Here are some outputs from system commands:

$ file my_binary_name
my_binary_name: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, with unknown capability 0xf41 = 0x756e6700, with unknown capability 0x70100 = 0x1040000, stripped

$ dpkg-architecture 
DEB_BUILD_ARCH=mipsel
DEB_BUILD_ARCH_OS=linux
DEB_BUILD_ARCH_CPU=mipsel
DEB_BUILD_ARCH_BITS=32
DEB_BUILD_ARCH_ENDIAN=little
DEB_BUILD_GNU_CPU=mipsel
DEB_BUILD_GNU_SYSTEM=linux-gnu
DEB_BUILD_GNU_TYPE=mipsel-linux-gnu
DEB_HOST_ARCH=mipsel
...

dpkg-architecture would be perfect for the task, except that it is not present on other Linux distributions.

The first problem was already addressed here: How to determine whether a given Linux is 32 bit or 64 bit?

The command

getconf LONG_BIT

properly reports 32 on my system.

But how do I determine whether it is big endian or little endian?

I figured out that config.guess can determine the difference, but it does so by running the compiler which may not be present on end user's computer. On top of that config.guess completely ignores the fact that operating system works in 32-bit mode and wrongly reports mips64el instead of mipsel.


Solution

  • The file command tells you:

    $ file my_binary_name

    my_binary_name: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, with unknown capability 0xf41 = 0x756e6700, with unknown capability 0x70100 = 0x1040000, stripped

    The LSB there stands for least-significant byte, meaning little endian. The output of file given a big-endian binary will be MSB, most-significant byte.

    Note that MIPS has 3 ABIs (actually more), one of which is n32. n32 has native 64-bit integers but only 32-bit pointers (and requires a 64-bit kernel).

    For n32 binaries file will still report 32-bit:

    ELF 32-bit LSB executable, MIPS, N32 MIPS-III version 1 (SYSV)

    o32 (what debian uses):

    ELF 32-bit LSB executable, MIPS, MIPS-III version 1 (SYSV)

    n64:

    ELF 64-bit LSB executable, MIPS, MIPS-III version 1 (SYSV)