AIX and Run-Time Linking

Almost all today’s programs under AIX are dynamically linked, i.e. necessary libraries are loaded and bound at runtime (run-time linking). But how does a program know which libraries are needed and in which directory they can be found? What can you do if a library is not found automatically? What is the meaning of the variables LIBPATH and LD_LIBRARY_PATH?

A small C program

In order to shed more light on these questions, we use the following small C program:

$ cat hello.c
#include <stdio.h>

int main()
{
        printf("hello world\n");
        return 0;
}

$

The program prints the line “hello world” using the function printf from the standard C library (libc.a).

We compile the program using the GNU C compiler (of course, any other C compiler is also possible):

$ gcc -o hello hello.c
$

And start the program:

$ ./hello
hello world
$

As expected, the program prints the message “hello world“. But how does the program know that the standard C library (libc.a) has to be linked and where it can be found?

The loader section of an executable program

This question can be answered using the dump command. The command dump shows selected parts of object files, archives (libraries) and executable files. With the option “-H” the so-called loader section can be displayed:

$ dump -H hello
hello:


                        ***Loader Section***
                      Loader Header Information
VERSION#         #SYMtableENT     #RELOCent        LENidSTR
0x00000001       0x0000000b       0x00000026       0x0000008d      


#IMPfilID        OFFidSTR         LENstrTBL        OFFstrTBL
0x00000002       0x000002f0       0x00000039       0x0000037d      



                        ***Import File Strings***
INDEX  PATH                          BASE                MEMBER             
0      /opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8.1.0:/opt/freeware/lib/gcc/powerpc-ibm-aix7.2.0.0/8.1.0/../../..:/usr/lib:/lib                                        
1                                    libc.a              shr.o              
$

(With 64-bit files the option “-X64” or “-Xany” must also be used.)

The library search path is stored under index 0. As with the shell’s PATH variable, directories are separated by colons. Required libraries are searched in the listed directories. As soon as a library is found, the other directories are no longer searched. The AIX operating system uses the path “/usr/lib:/lib” by default, the additional paths were added by the GNU C compiler. Following the library search path, the required libraries are listed, in our case the standard C library libc.a under index 1.

If you want to know in which directory a library is found (there could be a library called libc.a in more than one directory), you can use the command ldd:

$ ldd hello
hello needs:
         /usr/lib/libc.a(shr.o)
         /unix
         /usr/lib/libcrypt.a(shr.o)
$

The libc.a is therefore found under /usr/lib and depends on other libraries itself, hence the two other entries.

Meaning of LIBPATH and LD_LIBRARY_PATH

To show what happens if not all the required libraries can be found via the library search path, we compile our C program again, but with slightly different options:

$ gcc -o hello -Wl,-blibpath:- hello.c
$

The option “-Wl, -blibpath: –” ensures that “-” is now stored as the library search path in the executable generated:

$ dump -H hello
hello:


                        ***Loader Section***
                      Loader Header Information
VERSION#         #SYMtableENT     #RELOCent        LENidSTR
0x00000001       0x0000000b       0x00000026       0x00000012      


#IMPfilID        OFFidSTR         LENstrTBL        OFFstrTBL
0x00000002       0x000002f0       0x00000039       0x00000302      


                        ***Import File Strings***
INDEX  PATH                          BASE                MEMBER             
0      -                                                                    
1                                    libc.a              shr.o              
$

This means that the program can no longer find the standard C library at runtime and calling the program leads to the following error message:

$ ./hello
exec(): 0509-036 Cannot load program ./hello because of the following errors:
        0509-150   Dependent module libc.a(shr.o) could not be loaded.
        0509-022 Cannot load module libc.a(shr.o).
        0509-026 System error: A file or directory in the path name does not exist.
$

Everyone has probably seen this message at least once when the required libraries for a called program were missing. In such cases, an additional library search path can be set in the form of an environment variable. On AIX there are two variables available for this purpose, LIBPATH and LD_LIBRARY_PATH.

As we saw above, libc.a can be found under /usr/lib. We therefore set LIBPATH to /usr/lib and start our program again:

$ LIBPATH=/usr/lib ./hello
hello world
$

The libc.a is obviously found and the program works correctly again. Of course, you can also export the variable, in which case it does not have to be specified explicitly before the command.

Next we set LD_LIBRARY_PATH to /usr/lib and start our program again:

$ LD_LIBRARY_PATH=/usr/lib ./hello
hello world
$

Again, libc.a is found and the program works correctly again.

Finallye we investigate what happens when both variables are set.

We set LD_LIBRARY_PATH to /usr/lib and LIBPATH to the nonexistent directory /dummy:

$ LD_LIBRARY_PATH=/usr/lib LIBPATH=/dummy ./hello
exec(): 0509-036 Cannot load program ./hello because of the following errors:
        0509-150   Dependent module libc.a(shr.o) could not be loaded.
        0509-022 Cannot load module libc.a(shr.o).
        0509-026 System error: A file or directory in the path name does not exist.
$

The library libc.a is no longer found, although LD_LIBRARY_PATH contains the correct path. Obviously the variable LIBPATH has higher priority and the variable LD_LIBRARY_PATH is ignored!

We check this by setting LD_LIBRARY_PATH to /dummy and LIBPATH to /usr/lib:

$ LD_LIBRARY_PATH=/dummy LIBPATH=/usr/lib ./hello
hello world
$

The program works correctly again.

Conclusion

Libraries are searched in the following order:

  1. Using the library search path from the loader section of the executable program.
  2. If LIBPATH is set, search the paths from LIBPATH.
  3. Only if LIBPATH is not set: Search the paths from LD_LIBRARY_PATH (if set).

If both LIBPATH and LD_LIBRARY_PATH are set, then LD_LIBRARY_PATH is ignored.

 

Back to AIX