2.3. Resolving symbols at link-time

On AIX, symbol resolution is performed at link-time and cannot be rebound at the program load-time, except for the two exceptions explained in the following sections:

  • 2.5, “Run-time linking” on page 68

  • 2.6, “Dynamic loading” on page 82

This means that once an executable file was generated, dependent shared objects and archive members in libraries must be referenced using the same path name all the time; otherwise, the executable cannot run.

However, this does not necessary mean that dependent shared objects and archive members in libraries must be in the same directory all the time. If no path information is associated those objects and members, the system loader will look for them in several directories specified by the -L linker option (see 2.3.1, “The -L linker option” on page 55) and the LIBPATH environment variable (see 2.3.3, “LIBPATH environment variable” on page 58), in addition to the default library search directories, /usr/lib and /lib.

This mechanism simplifies the work of the system loader when a module is loaded, and thus results in better execution performance, though it could be seen rigid and tedious from the application programmers’ view.

To demonstrate this behavior, we have copied libc.a to /tmp and build an executable file from the program shown in Example 2-1 on page 43 as follows:

$ cp /usr/lib/libc.a /tmp
$ ls -l /tmp/libc.a
-r-x------   1 k5       k5          6793964 Apr 18 15:35 /tmp/libc.a
$ chmod a+r /tmp/libc.a
$ ls -l /tmp/libc.a
-r-xr--r--   1 k5       k5          6793964 Apr 18 15:35 /tmp/libc.a
$ cc helloworld.c /tmp/libc.a
				

Note

Shared objects or libraries must be readable from other users; otherwise they are treated as private shared objects (see 2.9.2, “Private shared objects” on page 101 for more detail).


The executable file cannot run if /tmp/libc.a is removed as follows:

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

The reason is that the reference information to the removed /tmp/libc.a file was statically stored in the XCOFF header of the executable file, as emphasized in Example 2-5 on page 55.

The directory path names, except for the first (index 0) section, shown in the PATH column are called optional path components for dependent modules. In Example 2-5 on page 55, libc.a has the optional path component /tmp.

Example 2-5. dump -H output with the full directory path name
$ dump -H a.out

a.out:

                        ***Loader Section***
                      Loader Header Information
VERSION#         #SYMtableENT     #RELOCent        LENidSTR
0x00000001       0x00000007       0x00000010       0x00000031

#IMPfilID        OFFidSTR         LENstrTBL        OFFstrTBL
0x00000002       0x00000188       0x0000002a       0x000001b9


***Import File Strings***
INDEX  PATH                          BASE                MEMBER
0      /usr/lpp/xlopt:/usr/lib:/lib
1      /tmp                          libc.a              shr.o

Note

It is always recommended to avoid having any optional path components when creating shared objects and libraries and building executable files, in order to avoid unnecessary dependency to the file path names of the dependent modules.


If the same program is built as follows:

$ cc helloworld.c

the XCOFF header will not contain any path name information for libc.a as highlighted in the following (the compiler driver automatically add -lc before invoking the linker in this case):

***Import File Strings***
INDEX  PATH                          BASE              MEMBER
0      /usr/lpp/xlopt:/usr/lib:/lib
1                                    libc.a            shr.o
				

Since libc.a has no path information, the system loader will look for this library from the directories (/usr/lpp/xlopt:/usr/lib/:/lib) listed in the first (index 0) loader header section of the XCOFF header of the generated executable file.

2.3.1. The -L linker option

If the program is referencing libraries, then use the -L and -l linker options rather than specifying library file path names directly.

For example, if the referenced library, libabc.a, is placed in the /project/test/lib directory, specify the options as follows:

$ cc -o a.out main.c -labc -L/project/test/lib
					

The linker adds the /project/test/lib directory in front of the default directory search path in order to look for referenced shared objects and libraries.

In this case, the directory name, /project/test/lib, will be added to in front of the first entry for the first (index 0) loader header section of the XCOFF header of the generated executable file, as shown in Example 2-6.

Example 2-6. dump -H with the PATH information
$ dump -H a.out

a.out:

                        ***Loader Section***
                      Loader Header Information
VERSION#         #SYMtableENT     #RELOCent       LENidSTR
0x00000001       0x00000007       0x00000010      0x00000037

#IMPfilID        OFFidSTR         LENstrTBL       OFFstrTBL
0x00000002       0x00000188       0x0000002a      0x000001bf


                        ***Import File Strings***
INDEX  PATH                          BASE               MEMBER
0     /project/test/lib:/usr/lpp/xlopt:/usr/lib:/lib
1                                    libabc.a             shr.o

When executing the command, if libabc.a is found in the directories shown in the following directories, the command can run:

/project/test/lib:/usr/lpp/xlopt:/usr/lib:/lib

Note

The shared objects and libraries must not have any optional path component information in the XCOFF loader header section to be searched from the directories listed in the first (index 0) loader header section of the executable file.


2.3.2. Searching objects and libraries at link-time

The linker can handle two types of files as input: object file or library. Those object files and libraries can be specified in the linker command line explained in this section.

Note

The order of libraries and objects specified on the linker command line is not important unless run-time linking (see 2.5, “Run-time linking” on page 68) is used.


Object files
  • Specify the absolute path name for the object file. For example:

    $ cc -o a.out main.c /prod/obj/shr1.o
    
  • Specify the relative path name for the object file. For example:

    $ cc -o a.out main.c ../../prod/obj/shr1.o
    
  • Specify the file name for the object file, if it resides in the current directory. For example:

    $ ls main.c shr.o
    main.c    shr.o
    $ cc -o a.out main.c shr1.o
    

Except for the last method, the generated executable file would have an optional path component for its dependent shared object shr.o in its XCOFF header, if shr.o is a shared object.

Libraries
  • Specify the absolute path name for the library. For example:

    $ cc -o a.out main.c /prod/lib/libabc.a
    
  • Specify the relative path name for the library. For example:

    $ cc -o a.out main.c ../../prod/lib/libabc.a
    
  • Specify the file name for the library, if it resides in the current directory. For example:

    $ ls main.c libabc.a
    libabc.a  main.c
    $ cc -o a.out main.c libabc.a
    
  • Specify the library installed directory using the -L and -l linker options. For example:

    $ cc -o a.out main.c -L/prod/lib -labc
    

Except for the last two methods, the generated executable file would have an optional path component for its dependent shared library libabc.a in its XCOFF header, if libabc.a is a shared library.

Note

The linker -bnoipath options instructs the command to not include any file path name information in the resultant module. The default option, -bipath, preserves file path name information.


2.3.3. LIBPATH environment variable

If the LIBPATH[13] environment variable is defined, the system loader refers to it in order to search referenced shared objects and libraries that contain shared archive members, when the executable file is invoked. The linker does not refer to LIBPATH in order to look for shared objects and libraries.

[13] On some other UNIX operating systems the LD_LIBRARY_PATH variable is used for a similar purpose. On AIX, however, LD_LIBRARY_PATH has no meaning.

The syntax of LIBPATH is:

LIBPATH=/path1:/path2:/path3:...

If defined, the system loader does the following processes when loading modules:

1.
Adds the text string value of LIBPATH in front of the PATH information stored in the first (index 0) loader header section of the XCOFF header of the executable.

2.
The system loader will search shared objects and libraries referenced by the executable in the directories in the order of the list created in the previous step.

Note

When a non-root user is attempting to run a setuid or setgid executable, only the directories listed in the header section of the executable are searched; the LIBPATH variable is ignored, even if it is set.


For example, if the LIBPATH environment variable is defined as follows when executing the program example used in 2.3.1, “The -L linker option” on page 55:

LIBPATH=/project/build/lib

then the system loader will search for the referenced shared objects and libraries in the following order:

  1. /project/build/lib

  2. /project/test/lib

  3. /usr/lpp/xlopt

  4. /usr/lib

  5. /lib

Note

The shared objects and libraries must not have any optional path component information in the XCOFF loader header section to be searched from the directories specified by the LIBPATH environment variable.


For example, assuming the following:

  • The shared object shr.o is linked with main.o in order to create the executable a.out.

  • Both shr.o and main.o are located in the current directory.

then you can select the following two methods to specify the file name shr.o in the command line to build the executable:

  1. cc -o a.out main.o shr.o

  2. cc -o a.out main.o ./shr.o

The executable file generated using the first method would have the loader information for shr.o, as shown in Example 2-7. In this case, the system loader will look for shr.o in the /usr/lpp/xlopt, /usr/lib, and /lib directories. If shr.o is stored in one of these directories, there is no need to set LIBPATH. If shr.o is stored in other than these directories, set the LIBPATH environment variable accordingly.

Example 2-7. dump -H without dot in PATH
$ dump -H a.out

a.out:

                       ***Loader Section***
                     Loader Header Information
VERSION#        #SYMtableENT     #RELOCent         LENidSTR
0x00000001      0x00000007       0x00000010        0x00000036

#IMPfilID       OFFidSTR         LENstrTBL         OFFstrTBL
0x00000003      0x00000188       0x0000002a        0x000001be

                       ***Import File Strings***
INDEX  PATH                         BASE                MEMBER
0      /usr/lpp/xlopt:/usr/lib:/lib
1                                   libc.a              shr.o
2                                   shr.o
					

For example, if shr.o is stored in the current directory, run the executable file after setting the variable as follows:

$ LIBPATH=$PWD ./a.out

If you have moved shr.o to /project/lib, then do the following:

$ LIBPATH=/project/lib ./a.out

If the executable is generated using the second method, the last five lines in Example 2-7 on page 59 would be:

***Import File Strings***
INDEX PATH                         BASE         MEMBER
0     /usr/lpp/xlopt:/usr/lib:/lib
1                                  libc.a       shr.o
2     .                            shr.o
					

The dot character in the PATH column for shr.o, which is an optional path component for shr.o, makes a big difference. When executing the executable generated with the second method, the system loader will not refer to LIBPATH nor the directories listed in the first (index 0) loader header section, in order to search shr.o. Therefore, shr.o must be located in the current directory whenever the executable file is invoked.

Using LIBPATH for modules could not be loaded

If a shared object cannot be found by the system loader when trying to start an executable, an error message similar to the following will be seen:

exec(): 0509-036 Cannot load program ex1 because of the following errors:
      0509-022 Cannot load library libone.so.
      0509-026 System error: A file or directory in the path name does not
exist.

The missing objects will be listed with 0509-022 error messages. Use the find command to search the system for the missing shared objects. If the object is found, try setting the LIBPATH environment variable to include the directory that contains the shared object and restart the application. Also, ensure that the object or library has read permission for the user trying to start the application.

A similar error message is produced when the system loader finds the specified shared objects, but not all of the required symbols can be resolved. This can happen when an incompatible version of a shared object is used with an executable. The error message is similar to the following:

exec(): 0509-036 Cannot load program ./example because of the following errors:
      0509-023 Symbol func1 in ex1 is not defined.
      0509-026 System error: Cannot run a file that does not have a valid
format.

The unresolved symbols are listed in the 0509-023 message lines. Write down the name of the unresolved symbol (func1), and use the dump -Tv command to determine which shared object the executable expects to resolve the symbol from. For example:

# dump -Tv example | grep function1
[4]     0x00000000    undef      IMP      DS EXTref libone.a(shr1.o) func1

This indicates that the executable is expecting to resolve the symbol func1 from the shared object shr1.o that is an archive member of libone.a. This information can help you start the problem determination process.

Note

To solve typical link-time errors, see 6.3, “Diagnosing link-time errors” on page 239.


2.3.4. Link-time and load-time

Shared objects and libraries are used in two stages when creating and executing an executable on AIX:

  1. At link-time, the link editor (the ld command) searches the specified shared objects and libraries to resolve all undefined symbols that are referenced in the generating executable file. If a shared object file or library contains the referenced symbols, the loader section of the XCOFF header of the created executable file should contain a reference to that shared object or library.

    In other words, symbols are exported from those shared objects or libraries and imported from the executable file.

  2. At the program load-time, the system loader (the kernel component that starts new processes) reads the XCOFF header information of the executable and attempts to locate any referenced shared libraries. Assuming all the referenced shared objects and libraries are found, the executable can be started. Then, the system loader attempts to load the sections in the executable file into the appropriate segments in the process address space, as explained in Table 2-2 on page 62. The program text in shared objects and libraries is loaded into the global system memory by the first program that needs it and is shared by all programs that use it.

Table 2-2. XCOFF headers and loading target segments
Program executable componentsCorresponding section header name in the XCOFF formatLoading target segment in the process address space
Program text.textProcess text segment
Program data (initialized and un-initialized).data and .bssProcess data segment
Referenced shared objectsloaderShared library text segment (per-process shared library data segment will be also populated with the necessary data for the process)

For the detailed information about the each segment usage in the process address space, see Chapter 3, “Understanding user process models” on page 105.

Figure 2-3 on page 63 depicts the processes done by the system loader at the program load-time.

Figure 2-3. An XCOFF format executable file and exec()


Technically, each section header in the XCOFF file provides an offset address to the actual section in the file. However, this is not shown in Figure 2-3 to avoid unnecessary complexity.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset