Weight: 1

Objectives

Candidates should be able to determine the shared libraries that executable programs depend on and install them when necessary.

  • Identify shared libraries.
  • Identify the typical locations of system libraries.
  • Load shared libraries.

Terms and Utilities

  • ldd
  • ldconfig
  • /etc/ld.so.conf
  • LD_LIBRARY_PATH

Linking

When we write a program, we use libraries. For example, if you need to read text from standard input, you need to link a library that provides this. Think linking has two forms:

  • Static Linking is when you add this library to your executable program. In this method, your program size is big because it has all the needed libraries. One good advantage is your program can be run without being dependent on other programs/libraries.
  • Dynamic Linking is when you just say in your program "We need this and that library to run this program". This way your program is smaller but you need to install those libraries separately. This makes programs more secure (Because libraries can be updated centrally, and more advanced any improvement in a library will improve the whole program), and smaller.

Linux dynamic libraries have names like libLIBNAME.so.VERSION and are located at places like /lib*/ and /usr/lib*/. On Windows, we call them Dynamic Linked Libraries (DLLs).

Dynamic linking is also called shared libraries because all the programs are sharing one library which is separately installed.

What libraries do I need

Libraries related to system utilities are installed in /lib and /lib64 (for 32bit and 64bit libraries) and libraries installed by other software will be located at /usr/lib and /usr/lib64.

ldd

The ldd command helps you find:

  • If a program is dynamically or statically linked
  • What libraries a program needs

Let's have a look at two files:

[[email protected] ~]$ ldd /sbin/ldconfig
    not a dynamic executable

[[email protected] ~]$ ldd /bin/ls
    linux-vdso.so.1 (0x00007ffdd53eb000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f5cbc7b0000)
    libcap.so.2 => /lib64/libcap.so.2 (0x00007f5cbc7a6000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f5cbc5a5000)
    libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f5cbc50f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f5cbc813es

As you can see, ldd tells us that the /sbin/ldconfig is not dynamically linked but shows us the libraries needed by /bin/ls.

Symbolic links for libraries

If you are writing a program and you use udev functions, you will ask for a library called libudev.so.1. But a Linux distro, might call its version of udev library libudev.so.1.4.0. How can we solve this problem? The answer is symbolic links; You will learn more about them in the next chapters but for short, a symbolic name is a new name for the same file.

I will check the same thing on my system. First I'll find where the libudev.so.1 on my system is:

# locate libudev.so.1
/lib/i386-linux-gnu/libudev.so.1
/usr/lib64/libudev.so.1.7.3

And then will check that file:

# ls -la /lib/i386-linux-gnu/libudev.so.1
lrwxrwxrwx 1 root root    16 Nov 13 23:05 /lib/i386-linux-gnu/libudev.so.1 -> libudev.so.1.4.0

As you can see, this is a symbolic link pointing to the version of libudev I have installed (1.4.0) so even if a software says it needs libudev.so.1, my system will use its libusdev.so.1.4.0.

Dynamic library configs and cache

Like most of the other Linux tools, dynamic linking is also configured by a textual configuration file. It is located at /etc/ld.so.conf and it might load more config files from /etc/ld.so.conf.d/*.conf. Please note that this including other files from /etc/ld.so.conf.d/ is a common practice to keep config files separated and clean. You will see the same pattern in many other places too and technically we were able to add whatever is needed in the original file.

[[email protected] ~]$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
[[email protected] ~]$ ls /etc/ld.so.conf.d/
llvm13-x86_64.conf  pipewire-jack-x86_64.conf
[[email protected] ~]$ cat /etc/ld.so.conf.d/llvm13-x86_64.conf
/usr/lib64/llvm13/lib

The ldconfig commands processed all these files to make the loading of libraries faster. This command creates ld.so.cache to locate files that are to be dynamically loaded and linked.

If you change the ld.so.conf (or sub-directories) you need to run ldconfig. Try it with -v switch to see the progress / data.

To close this section lets run ldconfig with the -p switch to see what is saved in ld.so.cache:

[[email protected] ~]$ ldconfig -p | head
1373 libs found in cache `/etc/ld.so.cache'
    libzstd.so.1 (libc6,x86-64) => /lib64/libzstd.so.1
    libzmf-0.0.so.0 (libc6,x86-64) => /lib64/libzmf-0.0.so.0
    libzip.so.5 (libc6,x86-64) => /lib64/libzip.so.5
    libzhuyin.so.13 (libc6,x86-64) => /lib64/libzhuyin.so.13
    libzck.so.1 (libc6,x86-64) => /lib64/libzck.so.1
    libz.so.1 (libc6,x86-64) => /lib64/libz.so.1
    libyui.so.15 (libc6,x86-64) => /lib64/libyui.so.15
    libyui-mga.so.15 (libc6,x86-64) => /lib64/libyui-mga.so.15
    libyelp.so.0 (libc6,x86-64) => /lib64/libyelp.so.0

As you can see, this file tells the kernel that if anyone asks for libzstd.so.1, the /lib64/libzstd.so.1 file should be loaded and used.

Where OS finds dynamic libraries

When a program needs a shared library, the system will search files in this order:

  1. LD_LIBRARY_PATH environment variable
  2. Programs PATH
  3. /etc/ld.so.conf (Which might load more files from /etc/ld.so.conf.d/ in its beginning or its end)
  4. /lib/, /lib64/, /usr/lib/, /usr/lib64/

In some cases, you might need to override the default system libraries. Some examples are:

  • You are running an old software which needs an old version of a library.
  • You are developing a shared library and want to test it without installing it
  • You are running a specific program (say from opt) which needs to access its own libraries

In these cases, you can point the environment variable LD_LIBRARY_PATH to the library you need to use and then run your program. A colon (:) separated list of directories will tell your program where to search for needed libraries before checking the libraries in /etc/ld.so.cache.

For example, if you give this command:

export  LD_LIBRARY_PATH=/usr/lib/myoldlibs:/home/jadi/lpic/libs/

And then run any command, the system will search /usr/lib/myoldlibs and then /home/jadi/lpic/libs/ before going to the main system libraries (defined in /etc/ld.so.cache). . .

Loading dynamically

In the last part of this section, let's see how we can manually tell Linux to run a program using its dynamic linker. Its also called a dynamic loader and is used to load dynamic libraries needed by an executable. It might be called ld or ld-linux. You can find yours by running:

[[email protected] ~]$ locate ld-linux
/usr/lib64/ld-linux-x86-64.so.2
/usr/share/man/man8/ld-linux.8.gz
/usr/share/man/man8/ld-linux.so.8.gz

and run programs using it like this:

[jadi@fedora ~]$ /usr/lib64/ld-linux-x86-64.so.2 /usr/bin/ls
Desktop  Documents  Downloads  Music  Pictures  Public  Templates  tmp  Videos

Do you want to go deeper than LPIC1 and ask why you do not need to run ld-linux when running a command? Because the executable you are running is a Linux ELF executable and if you check its inside, you can see that it says "run this using ld-linux":

[[email protected] ~]$ readelf -Wl /usr/bin/ls

Elf file type is DYN (Position-Independent Executable file)
Entry point 0x6c00
There are 13 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0002d8 0x0002d8 R   0x8
  INTERP         0x000318 0x0000000000000318 0x0000000000000318 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x003798 0x003798 R   0x1000
  LOAD           0x004000 0x0000000000004000 0x0000000000004000 0x013c21 0x013c21 R E 0x1000
  LOAD           0x018000 0x0000000000018000 0x0000000000018000 0x0074d8 0x0074d8 R   0x1000
  [...]

๐Ÿ’€ There is a hack here: You can run any Linux executable even if its executable bit is not set! just run it using ld-linux as we did a few lines above!


โ† 102.2 Install a boot manager
Chapter List
102.4 Use Debian package management โ†’

Category

LPIC1

Tags

Contact