28

In my laptop:

$ cat /etc/issue  
Ubuntu 18.04 LTS \n \l

There are two different folders for libraries x86 and x86_64:

~$ ls -1 /  
bin
lib
lib64
sbin
...

Why for binaries exists only one directory?

P.S. I'm also interested in Android but I hope that answer should be the same.

5
  • 1
    Only in one? I see both /bin and /sbin there. What is the question? Are you asking about the difference between /lib and /lib64?
    – Kusalananda
    Jun 2, 2018 at 20:01
  • 2
    @Kusalananda, I mean that there is no independent folder for x86_64 (neither for /bin no for /sbin).
    – Gluttton
    Jun 2, 2018 at 20:03
  • 7
    IMO OP wants to know why there is no /bin64. Jun 2, 2018 at 20:03
  • The approximately one application that benefits from having both 32-bit and 64-bit versions (WINE) gets around it by having different-named binaries (wine*32 and wine*64). Jun 2, 2018 at 22:57
  • 1
    @IgnacioVazquez-Abrams: it also needs to be said that you link binaries against libraries, not vice versa. So binaries don't need to be partitioned by 32/64-bitness.
    – smci
    Jun 3, 2018 at 1:48

2 Answers 2

26

First, why there are separate /lib and /lib64:

The Filesystem Hierarchy Standard mentions that separate /lib and /lib64 exist because:

10.1. There may be one or more variants of the /lib directory on systems which support more than one binary format requiring separate libraries. (...) This is commonly used for 64-bit or 32-bit support on systems which support multiple binary formats, but require libraries of the same name. In this case, /lib32 and /lib64 might be the library directories, and /lib a symlink to one of them.

On my Slackware 14.2 for example there are /lib and /lib64 directories for 32-bit and 64-bit libraries respectively even though /lib is not as a symlink as the FHS snippet would suggest:

$ ls -l /lib/libc.so.6
lrwxrwxrwx 1 root root 12 Aug 11  2016 /lib/libc.so.6 -> libc-2.23.so
$ ls -l /lib64/libc.so.6
lrwxrwxrwx 1 root root 12 Aug 11  2016 /lib64/libc.so.6 -> libc-2.23.so

There are two libc.so.6 libraries in /lib and /lib64.

Each dynamically built ELF binary contains a hardcoded path to the interpreter, in this case either /lib/ld-linux.so.2 or /lib64/ld-linux-x86-64.so.2:

$ file main
main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, not stripped
$ readelf  -a main  | grep 'Requesting program interpreter'
      [Requesting program interpreter: /lib/ld-linux.so.2]

$ file ./main64
./main64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, not stripped
$ readelf  -a main64  | grep 'Requesting program interpreter'
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

The job of the interpreter is to load necessary shared libraries. You can ask a GNU interpreter what libraries it would load without even running a binary using LD_TRACE_LOADED_OBJECTS=1 or a ldd wrapper:

$ LD_TRACE_LOADED_OBJECTS=1 ./main
        linux-gate.so.1 (0xf77a9000)
        libc.so.6 => /lib/libc.so.6 (0xf760e000)
        /lib/ld-linux.so.2 (0xf77aa000)
$ LD_TRACE_LOADED_OBJECTS=1 ./main64
        linux-vdso.so.1 (0x00007ffd535b3000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f56830b3000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f568347c000)

As you can see a given interpreter knows exactly where to look for libraries - 32-bit version looks for libraries in /lib and 64-bit version looks for libraries in /lib64.

FHS standard says the following about /bin:

/bin contains commands that may be used by both the system administrator and by users, but which are required when no other filesystems are mounted (e.g. in single user mode). It may also contain commands which are used indirectly by scripts.

IMO the reason why there are no separate /bin and /bin64 is that if we had the file with the same name in both of these directories we couldn't call one of them indirectly because we'd have to put /bin or /bin64 first in $PATH.

However, notice that the above is just the convention - the Linux kernel does not really care if you have separate /bin and /bin64. If you want them, you can create them and setup your system accordingly.

You also mentioned Android - note that except for running a modified Linux kernel it has nothing to do with GNU systems such as Ubuntu - no glibc, no bash (by default, you can of course compile and deploy it manually), and also directory structure is completely different.

7
  • Your ls -l examples aren't particularly germane. What would be useful is the output of ls -l /lib /lib64, which probably shows that /lib itself is a symlink. Jun 3, 2018 at 9:48
  • You meant ls -ld, and no, /lib is not a symlink on my Slackware 14.2 system. Jun 3, 2018 at 9:50
  • Libraries have different md5sums: dfd029d25c58831bc5db671aec99a36f /lib64/libc.so.6, 987e7b736f316cc8da87ca2f38dae93e /lib/libc.so.6. Jun 3, 2018 at 9:51
  • 2
    In that case, showing the symlinks in-directory doesn't connect to the citation. Jun 3, 2018 at 9:55
  • 1
    LD_TRACE_LOADED_OBJECTS=1 is obsolete due to a security hole and ldd doesn't use it anymore. Reason: ldd /path/to/malicious-static-binary was used to take over systems because sysadmins were expecting ldd to only look at the binary not run it. Also, checking for static or not is inadequate as a binary can be constructed to use a malicious loader instead.
    – Joshua
    Jun 3, 2018 at 18:35
23

The reason is that the lib/lib64 directories can contain files which happen to have the same name because those are libraries shared with diverse programs. Putting them in separate directories solves the conflict. There's (usually...) no good reason for distributing same-named executables on the same system which are 32/64-bit, but since there can be a mixture of executables, the shared libraries have to be provided for.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .