The linker and dynamic loader provide linking and loading behaviors found widely across the Unix industry, considered, with the SVR4 standards, to define the de facto industry standards. The following linker behavior is compliant with de facto industry standard:
ELF object file format and libelf(3E) routines
Dynamic path searching
Library-level versioning
dl* family of dynamic
loading routines
Breadth-first symbol searching
The HP-UX 11i version 1.5 release maintains certain compatibility behaviors to make transition from PA-32 to IPF mode easier:
Creation of default run-time path
environment variable (RPATH) if
no ld +b is seen on the link line,
to improve transition from the PA-32 linker.
ld +compat option
for compatibility with PA-32 linking and loading behavior.
Starting with the HP-UX 11.00 release, the linker toolset supports the ELF (executable and linking format) object file format. The linker toolset provides new tools to display and manipulate ELF files. The libelf(3E) library routines provide access to ELF files. The command elfdump(1) displays contents of an ELF file.
See the HP-UX Software Transition Toolkit (STK) at http://www.software.hp.com/STK/
for more information on the structure of ELF object files.
This section introduces new features of the IPF linker for HP-UX 11i version 1.5.
The linker toolset provides the following new features for developing IPF programs:
Option |
Action |
|---|---|
|
Routines for manipulating shared libraries. |
|
Routines for manipulating the ELF object
file format. Includes the |
|
A tool that displays information about an ELF object file. |
|
A tool that shows shared libraries used by a program or shared library. |
New options to |
Command line options to assist in the development of IPF applications. |
Standard SVR4 dynamic loading features |
Includes SVR4 dynamic path searching and breadth-first symbol searching. |
Mapfile support |
A linker option that lets you control the organization of segments in executable files. This feature is intended for embedded systems development. |
The IPF linker toolset does not support the following PA-32 mode features.
Option or Behavior |
Description |
|---|---|
|
Specifies incremental loading. IPF applications must use shared libraries instead. |
|
Does parameter type checking. This option is unsupported. |
|
Generates an initial program loader header file. This option is unsupported. |
|
Save data and relocation information in temporary files to reduce virtual memory requirements during linking. This option is unsupported. |
|
Generates an executable with file type
|
|
Causes the data segment to be placed
immediately after the text segment. This option is accepted but
ignored in 64-bit mode. If this option is used because your application
data segment is large, then the option is no longer needed in 64-bit
mode. It can be use in 32-bit and IPF applications. If this option is used because your program is used in an
embedded system or other specialized application, consider using
mapfile support with the |
|
Specifies pathname for compiling I-SOMs to SOMs. This option is unsupported. |
| Share library suffix | In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit), the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix. |
+objdebug mode
|
In IPF (32-bit and 64-bit), the compiler option +objdebug
is the default. When used with -g, the +objdebug option
leaves debug information in the object files instead of copying it to the
executable file at link time, resulting in shorter link times and smaller
executables. The +noobjdebug option can be used to override the +objdebug
option and copy all debug information to the executable file.
|
+nosrcpos
|
In IPF (32-bit and 64-bit), the +srcpos option is
the default. The +srcpos option causes the compiler to generate
part of the debug information even when the -g compiler option is
not specified. The +srcpos option also causes part of the
debug information to be always copied over to the executable file resulting in
larger executables. The +srcpos option enables users to profile
programs using tools like CXperf and HP Caliper, or compiler options like +I and +P, even in the absence of -g
compilation. The linker option +nosrcpos can be used to
override the +srcpos option and strip the associated debug
information during link time. The +nosrcpos option can also be
used with -g +objdebug to fully enforce the +objdebug mode (i.e.,
leaving the debug information in the object files).
|
odump |
The |
Intra-library versioning |
Specified by using the In PA-32 mode, the linker lets you version your library by object files. IPF or PA-64 applications must use SVR4 library-level versioning instead. |
Duplicate code and data symbols |
Code and data cannot share the same namespace in IPF mode. You should rename the conflicting symbols. |
All internal and undocumented linker options |
These options are unsupported. |
IPF applications (32-bit and 64-bit) and PA-64 applications use a run-time dynamic loading model similar to other SVR4 systems. There are two main areas where the IPF/PA-64 program startup differs from PA 32-bit mode:
Dynamic path searching for shared libraries.
Symbol searching in dependent libraries.
It is recommended that you use the standard SVR4 linking option
(+std), which is on by default
when linking IPF (32-bit and 64-bit) and PA-64 applications.
There may be circumstances while you transition, that you need PA-32-compatible
linking behavior. The IPF and PA-64 linkers provides the mode +compat
option to force the linker to use PA-32 linking and dynamic loading
behavior.
The following table summarizes the dynamic loader differences between PA-32 and IPF/PA-64 bit modes (IPF (64-bit and 32-bit) and PA-64):
Linker and Loader Functions |
PA-32 Mode Behavior |
IPF (32-bit and 64-bit) and PA-64 Mode Behavior |
|---|---|---|
|
Ordering is significant. |
Ordering is insignificant by default. Use |
Symbol searching in dependent libraries |
Depth-first search order. |
Breadth-first search order. Use
|
Run time path environment variables |
No run time environment variables by default. If |
Use
|
|
|
Add all directories
specified in |
This section provides a description and examples of dynamic path searching for shared libraries.
Dynamic path searching is the process that allows you to specify the location of shared libraries at run time. In PA-32 mode, you can enable run-time dynamic path searching of shared libraries in two ways:
By linking the program with +s,
enabling the program to use the path list defined by the SHLIB_PATH
environment variable at run time.
By storing a directory path list in the program
with the linker option +b path_list.
If +s or +b
path_list is enabled, all shared libraries
specified with the -l library
or -l:library
linker options are subject to a dynamic path lookup at run time.
In IPF, the dynamic path searching behavior has changed (same as PA-64 mode):
The +s
dynamic path searching option is enabled by default. It is not enabled
by default in PA-32 mode.
The LD_LIBRARY_PATH
environment variable is available in addition to the SHLIB_PATH
environment variable.
An embedded run-time path list called RUNPATH
may be stored in the executable. If +b
path_list is specified at link time,
these directories are added to RUNPATH.
If +b path_list
is not specified, the linker creates a default RUNPATH
consisting of:
directories in the -L
option (if specified), followed by
directories in the LPATH
environment variable (if specified).
By default, the linker ignores the ordering of the
+b path_list
and +s options.
At run time, the dynamic loader searches directory paths in the following order:
LD_LIBRARY_PATH
(if set)
SHLIB_PATH (if
set)
RUNPATH
the default location /usr/lib/hpux32
for 32-bit programs and /usr/lib/hpux64
for 64-bit programs.
The following are examples of specifying library paths in PA-32 mode and IPF/PA-64 mode (IPF (32-bit and 64-bit) and PA-64):
Linking to libraries by fully qualifying
paths and the library does not contain SONAME, which is specified
by the linker +h option when building
the shared library:
In this example, the program is linked with /opt/myapp/mylib.s:
$ cc main.o /opt/myapp/mylib.s Perform 32-bit link.
$ cc +DD64 main.o /opt/myapp/mylib.s Perform 64-bit link.
At run-time, in both 32-bit and 64-bit mode, the dynamic loader
only looks in /opt/myapp to find
mylib.s.
Linking to libraries using the -l
library or -l:library options:
In this example, the +s option
is not explicitly enabled at link time. Both 32-bit and 64-bit versions
of a shared library called libfoo.s
exist in the default location.
PA-32, IPF 32-bit mode example:
$ cc main.o -lfoo -o main Perform 32-bit link.
With the +DD32 default, when
linked in PA-32 mode, main
aborts at run time if libfoo.sl
is moved from /usr/lib. This is
because the absolute path name of the shared library /usr/lib/libfoo.sl
is stored in the executable.
When linked in IPF 32-bit mode, main
does not abort at run time if libfoo.s
is moved from /usr/lib/hpux32 as
long as LD_LIBRARY_PATH or SHLIB_PATH
is set and point to libfoo.s.
PA-64, IPF 64-bit mode example:
$ cc +DD64 main.o -lfoo -o main Perform 64-bit link.
When linked in IPF or PA-64 mode, main
will not abort at run time if libfoo.s
is moved, as long as LD_LIBRARY_PATH
or SHLIB_PATH is set and point
to libfoo.s.
Linking to libraries using -L
and +b path_list:
The -L option is used by
the linker to locate libraries at link time. The +b
option is used to embed a library path list in the executable for
use at run time.
PA-32, IPF 32-bit mode example:
$ cc main.o -L. -Wl,+b/var/tmp -lme Link the program.
$ mv libme.s /var/tmp/libme.sl Move libme.sl.
$ a.out Run the program.
In PA-32 mode, the dynamic loader searches paths to resolve external references in the following order:
/var/tmp
to find libme.sl found
/var/tmp to find
libc.sl not found
/usr/lib/libc.sl
found
In IPF 32-bit mode, the dynamic loader searches paths to resolve external references in the following order:
LD_LIBRARY_PATH
(if set) to find libme.s not found
SHLIB_PATH (if
set) to find libme.s not found
/var/tmp to find
libme.s found
LD_LIBRARY_PATH
(if set) to find libc.s not found
SHLIB_PATH (if
set) to find libc.s not found
/var/tmp to find libc.s
not found
/usr/lib/hpux32/libc.so
found
LD_LIBRARY_PATH
(if set) to find libc.s not found
SHLIB_PATH (if
set) to find libc.s not found
/var/tmp to find
libc.s not found
/usr/lib/hpux32/libc.so found
PA-64, IPF 64-bit mode example:
$ cc +DD64 main.o -L. -Wl,+b/var/tmp -lme Link the program.
$ mv libme.sl /var/tmp/libme.s Move libme.s.
$ a.out Run the program.
The dynamic loader searching order is the same in PA-64 and IPF (32-bit and 64-bit). The dynamic loader searches paths to resolve external references in the following order:
LD_LIBRARY_PATH
(if set) to find libme.s not found
SHLIB_PATH (if
set) to find libme.s not found
/var/tmp to find
libme.s found
LD_LIBRARY_PATH
(if set) to find libc.s not found
SHLIB_PATH (if
set) to find libc.s not found
/var/tmp to find
libc.s not found
/usr/lib/pa20_64/libc.sl
(PA-64) or /usr/lib/hpux32/libc.so
(IPF 32-bit) or /usr/lib/hpux64/libc.so
(IPF 64-bit) found
In IPF (32-bit and 64-bit) and PA-64 mode, the dynamic loader searches shared libraries using a breadth-first search order. Breadth-first symbol searching is used on all SVR4 platforms.
In PA-32 mode, the dynamic loader searches shared libraries using a depth-first search order.
The diagram below shows an example program with shared libraries and compares the two search methods:
a.out
|
|-----------------|
| |
lib1 lib2
|
lib3
Breadth-first search list: a.out -> lib1 -> lib2 -> lib3
Depth-first search list: a.out -> lib1 -> lib3 -> lib2
The commands to build the libraries and the executable in "Search Order of Dependent Libraries" are shown:
ld -b lib2.o -o lib2.s
ld -b lib3.o -o lib3.s
ld -b lib1.o
-L. -l3 -o lib1.s
cc main.o -Wl,-L. -l1 -l2 -o main
In PA-32 mode, if a procedure called same_name() is defined in both lib3 and lib2, main calls the procedure defined in lib3. In PA-64 and IPF (32-bit and 64-bit), main calls the procedure in lib2.
This section describes the system library locations and changes to the library name extension.
IPF HP-UX systems provide two new subdirectories called
hpux32 and hpux64
under /usr/lib directory for IPF
system and HP product libraries.
The diagram below shows the new directory structure:
/(root)
|
|-------------------------------------|
| |
opt usr
| |
application lib
| |
lib |----------|---------|
| | |
|----|-----| hpux32 hpux64
hpux32 hpux64
The linker automatically finds the correct set of system libraries depending on whether the application is compiled as a 32-bit or 64-bit application.
Library providers are encouraged to supply both 32-bit and 64-bit versions of application libraries. Be sure to develop a strategy for library naming conventions, directory structures, link-time options, and run-time environment variables.
IPF (32-bit and 64-bit) shared libraries are suffixed with .so,
which is different from the PA-RISC shared libraries, which are
suffixed with .sl. The IPF linker
supports shared libraries with both .so
and .sl extension.
For example, /usr/lib/hpux32/libc.so
is the IPF system 32-bit C library whereas /usr/lib/libc.sl
is the PA-RISC system 32-bit C library.
Use the compiler -complete
option or the linker -noshared option to create a statically-bound program. The default is -dynamic.
The following changes are planned in future releases.
Future of ld +compat
option
The +compat linker option
and support of compatibility mode may be discontinued in a future
release.
Support of shl_load
shared library management routines
A future release may discontinue support of the shl_load
family of shared library management routines.
The Linker and Libraries Online User Guide
is available as online help with HP-UX Operating System. You can
access online help through your HTML browser, as defined in the
BROWSER environment variable.
To access the Linker and Libraries Online User
Guide from the ld
command line:
ld +help
This chapter describes the process of compiling and linking a program.
Compiling Programs on HP-UX: An Example provides an overview of compiling on HP-UX.
Looking "inside" a Compiler describes the process of creating an executable file in more detail.
Linking Programs on HP-UX describes how ld
creates an executable file from one or more object files.
Linking with Libraries describes conventions for
using libraries with ld.
Running the Program describes the process of loading and binding programs at run time.
Linker Thread-Safe Features describes the thread-safe features.
To create an executable program, you compile a source file
containing a main program. For example, to compile an ANSI C program
named sumnum.c,
shown below, use this command (-Aa
says to compile in ANSI mode):
$ cc -Aa sumnum.c
The compiler displays status, warning, and error messages
to standard error output (stderr).
If no errors occur, the compiler creates an executable file named
a.out in the
current working directory. If your PATH
environment variable includes the current working directory, you
can run a.out
as follows:
$ a.out Enter a number: 4 Sum 1 to 4: 10
The process is essentially the same for all HP-UX compilers.
For instance, to compile and run a similar FORTRAN program named
sumnum.f:
$ f90 sumnum.f Compile and link sumnum.f.
... The compiler displays any messages here.
$ a.out Run the program.
... Output from the program is displayed here.
Program source can also be divided among separate files. For
example, sumnum.c
could be divided into two files: main.c,
containing the main program, and func.c,
containing the function sum_n.
The command for compiling the two together is:
$ cc -Aa main.c func.c main.c: func.c:
Notice that cc
displays the name of each source file it compiles. This way, if
errors occur, you know where they occur.
#include <stdio.h> /* contains standard I/O defs */
int sum_n( int n ) /* sum numbers from n to 1 */
{
int sum = 0; /* running total; initially 0 */
for (; n >= 1; n--) /* sum from n to 1 */
sum += n; /* add n to sum */
return sum; /* return the value of sum */
}
main() /* begin main program */
{
int n; /* number to input from user */
printf("Enter a number: "); /* prompt for number */
scanf("%d", &n); /* read the number into n */
printf("Sum 1 to %d: %d\\n", n, sum_n(n)); /* display the sum */
}
Generally speaking, the compiler reads one or more source
files, one of which contains a main program, and outputs an executable
a.out file, as
shown in Figure 1: High-Level
View of the Compiler .
| NOTE | If multiple definitions of a symbol occur in the specified
libraries, |
An executable file is created after the program has been compiled and linked. The next step is to run or load the program.
When you run an executable file created by ld,
the program is loaded into memory by the HP-UX program loader, exec.
This routine is actually a system call and can be called by other
programs to load a new program into the current process space. The
exec function
performs many tasks; some of the more important ones are:
Determine how to load the executable file by looking at its magic number. (See Also The a.out File .)
Determine where to begin execution of the program
- that is, the entry point - For examples in share-bound
executables in dld.so, in archive-bound executables in crt0.o.
(See Also The crt0.o Startup File.)
When the program uses shared libraries, the crt0.o
startup code invokes the dynamic loader (dld.so),
which in turn attaches any required shared libraries. If immediate
binding was specified at link time, then the libraries are bound
immediately. If deferred binding was specified, then libraries are
bound as they are referenced. (See Also What are Shared Libraries?.)
For details on exec,
see the exec(2) page in the HP-UX
Reference.
Since shared library routines and data are not actually contained
in the a.out
file, the dynamic loader must attach the
routines and data to the program at run time. Attaching a shared
library entails mapping the shared library code and data into the
process's address space, relocating any pointers in the shared library
data that depend on actual virtual addresses, allocating the bss
segment, and binding routines
and data in the shared library to the program.
The dynamic loader binds only those symbols that are reachable
during the execution of the program. This is similar to how archive
libraries are treated by the linker; namely, ld
pulls in an object file from an archive library only if the object
file is needed for program execution.
To accelerate program startup time, routines in a shared library are not bound until referenced. (Data items are always bound at program startup.) This deferred binding of shared library routines distributes the overhead of binding across the execution time of the program and is especially expedient for programs that contain many references that are not likely to be executed. In essence, deferred binding is similar to demand-loading.
The dynamic loader (dld.so)
and its application interface library (libdld.so)
are thread-safe.
Also, the linker toolset provides thread local storage support in:
ld
- the link editor
crt0.o
- the program startup file
Thread local storage (also called thread-specific data) is data specific to a thread. Each thread has its own copy of the data item.
| NOTE | Use of the |
See your HP compiler documentation
to learn how to create thread local storage data items with the
_thread compiler
directive.
See Programming with Threads on HP-UX for information on threads.
You have a great deal of control over how the
linker links your program or library by using ld
command-line options.
Using the Compiler Command
Using the Linker Command
In many cases, you use your compiler command to compile and link programs. Your compiler uses options that directly affect the linker.
By default, the linker searches the directories /usr/lib/hpux32
and /usr/ccs/lib/hpux32 for 32-bit
mode libraries, and /usr/lib/hpux64
and /usr/ccs/lib/hpux64
for 64-bit mode libraries specified with the -l
compiler option. (If the -p
or -G compiler
option is specified, then the linker also searches the profiling
library directory /usr/lib/libp.)
The -L
libpath option to ld
augments the default search path; that is, it causes ld
to search the specified libpath before
the default places. The C compiler (cc),
the aC++ compiler (CC),
and the HP Fortran 90 compiler (f90)
recognize the -L
option and pass it directly to ld.
To make the f90 compiler
search /usr/local/lib to find a
locally developed library named liblocal,
use this command line:
$f90 prog.f90 -L/usr/local/lib -llocal
(The f90 compiler searches
/opt/fortran90/lib and /usr/lib
as default directories.)
For the C compiler, use this command line:
$ cc -Aa prog.c -L /usr/local/lib -llocal
The LPATH
environment variable provides another way to override the default
search path. For details, see Changing the
Default Library Search Path with -L, LPATH, and $ORIGIN .
The -v
option makes a compiler display verbose information. This is useful
for seeing how the compiler calls ld.
For example, using the -v
option with the C compiler shows that it automatically links
with libsin,
and libc.
$ cc -v himom.c cc: informational note 404: NLSPATH is /opt/ansic/lib/nls/msg/%L/%N.cat:/opt/ansic/lib/nls/msg/C/%N.cat: cc: informational note 404: INCLUDIR is INCLUDIR=3D/usr/include cc: informational note 404: CCOPTS is not set. main.c: /opt/langtools/lbin/cpp.ansi main.c /var/tmp/ctmAAAa21620\\ -D__hpux -D__unix -D_FLT_EVAL_METHOD=3D0 -D__ia64\\ -D_INLINE_ASM -D_ILP32 -D_BIND_LIBCALLS\\ -D_Math_errhandling=3D(MATH_ERREXCEPT|MATH_ERRNO) cc: informational note 411: Entering Preprocessor. /opt/ansic/lbin/ccom /var/tmp/ctmAAAa21620 main.o -n main.c\\ -dynamic -DSblended -DD32 -ESdefaultstack\\ -Oq01,al,ag,cn,sz,Ic,vo,mf,Po,es,rs,sp,in,cl,om,vc,pi,\\ fa,Pe,Rr,pa,nf,cp,lx,Pg,ug,lu,lb,uj,dn,ap,rp,Fs,bp,wp,pc,mp,\\ LR,cx,cr,pi,so,Rc,fa,fe,pt,st,lc,Bl! -Aa func.c: /opt/langtools/lbin/cpp.ansi func.c /var/tmp/ctmAAAa21620\\ -D__hpux -D__unix -D_FLT_EVAL_METHOD=3D0 -D__ia64\\ -D_INLINE_ASM -D_ILP32 -D_BIND_LIBCALLS\\ -D_Math_errhandling=3D(MATH_ERREXCEPT|MATH_ERRNO) cc: informational note 411: Entering Preprocessor. /opt/ansic/lbin/ccom /var/tmp/ctmAAAa21620 func.o -n func.c\\ -dynamic -DSblended -DD32 -ESdefaultstack\\ -Oq01,al,ag,cn,sz,Ic,vo,mf,Po,es,rs,sp,in,cl,om,vc,pi,fa,\\ Pe,Rr,pa,nf,cp,lx,Pg,ug,lu,lb,uj,dn,ap,rp,Fs,bp,wp,pc,mp,LR,\\ cx,cr,pi,so,Rc,fa,fe,pt,st,lc,Bl! -Aa cc: informational note 404: LPATH is /usr/lib/hpux32:/opt/langtools/lib/hpux32: /usr/ccs/bin/ld -u__sin_core__ -u__sin_init -h__sin_core__\\ -h__sin_lookup_ibt -lsin -u main main.o func.o -lm -dynamic\\ +Oprocelim -lc cc: informational note 413: Entering Link editor.
The -Wl
option passes options and arguments to ld
directly, without the compiler interpreting the options. Its syntax
is:
-Wl,arg1 [,arg2]...
where each argn is an option or
argument passed to the linker. For example, to make ld
use the archive version of a library instead of the shared, you
must specify -a archive
on the ld command
line before the library.
The command for telling the linker to use an archive version
of libm from the C command line
is:
$ cc -Aa mathprog.c -Wl,-a,archive,-lm,-a,default
The command for telling the linker to use an archive version
of libm is:
$ ld /opt/langtools/lib/crt0.o mathprog.o -a archive -lm \ -a default -lc
The -o
name option causes ld
to name the output file name instead
of a.out. For
example, to compile a C program prog.c
and name the resulting file sum_num:
$ cc -Aa -o sum_num prog.c Compile using -o option. $ sum_num Run the program. Enter a number to sum: 5 The sum of 1 to 5: 15
Sometimes programs call routines not contained in the default
libraries. In such cases you must explicitly specify the necessary
libraries on the compile line with the -l
option. The compilers pass -l
options directly to the linker before the C libraries, but after the
SIN library.
For example, if a C program calls library routines in the
curses library (libcurses),
you must specify -lcurses
on the cc command
line:
$ cc -Aa -v cursesprog.c -lcurses
...
/usr/ccs/bin/ld /usr/ccs/lib/hpux32/crt0.o -u main \
cursesprog.o -lcurses -lc
the POSIX
cc: informational note 413: Entering Link editor.
The -c
compiler option suppresses the link-edit phase. That is, the compiler
generates only the .o
files and not the a.out
file. This is useful when compiling source files that contain only
subprograms and data. These may be linked later with other object
files, or placed in an archive or shared library. The resulting
object files can then be specified on the compiler command line,
just like source files. For example:
$ f90 -c func.f Produce .o for func.f. $ ls func.o func.o Verify that func.o was created. $ f90 main.f func.o Compile main.f with func.o $ a.out Run it to verify it worked.
This section describes linker commands for the 32-bit and 64-bit linker.
| NOTE | Unless otherwise noted, all examples show 32-bit behavior. |
In default mode, you do not need to include crt0.o
on the link line. However, you must include crt0.o
on the link line for all fully archive links (ld -noshared)
and in compatibility mode (+compat).
You do not need to include the crt0.o
startup file on the ld command
line for shared bound links.The dynamic loader, dld.so,
does some of the startup duties previously done by crt0.o.
See The crt0.o Startup File, and crt0(3) manual page for more information.
You can change or override the default linker search path
by using the LPATH
environment variable, the -L
linker option, or the +origin linker
option.
The LPATH
environment variable allows you to specify which directories ld
should search. If LPATH
is not set, ld
searches the default directory /usr/lib.
If LPATH is
set, ld searches
only the directories specified in LPATH;
the default directories are not searched unless they are specified
in LPATH.
If set, LPATH
should contain a list of colon-separated directory path names ld
should search. For example, to include /usr/local/lib
in the search path after the default directories, set LPATH
as follows:
$ LPATH=/usr/lib:/usr/local/lib Korn and Bourne shell syntax. $ export LPATH
The -L
option to ld
also allows you to add additional directories to the search path.
If -L libpath
is specified, ld
searches the libpath directory before
the default places.
For example, suppose you have a locally developed version
of libc, which
resides in the directory /usr/local/lib.
To make ld find
this version of libc
before the default libc,
use the -L option
as follows:
$ ld prog.o -L /usr/local/lib -lc
Multiple -L
options can be specified. For example, to search /usr/contrib/lib
and /usr/local/lib
before the default places:
$ ld prog.o -L /usr/contrib/lib \ -L /usr/local/lib -lc
If LPATH
is set, then the -L
option specifies the directories to search before the directories
specified in LPATH.
The +origin
option to ld
instructs the linker to search for the library in the directory
from which the object module originated.
The +origin option only apples
to the shared library specified directly afterwards, for example,
libc.so or -lc.
At runtime, if the dynamic loader cannot find the library
found in the path specified by $ORIGIN,
it attempts to search paths according to the search path algorithm
described above.
The syntax is as follows:
$ ld main.o +origin -lc
or
$ld main.o +origin /usr/lib/hpux32/libc.so
You can use the $ORIGIN string
in LD_LIBRARY_PATH, SHLIB_PATH,
RUNPATH (the embedded path or RPATH),
or in the path of a shared library in the shared library list. If
the DF_ORIGIN flag is set, the
loader determines the path of the current load module when the load
module is first loaded. If the DF_ORIGIN
flag is not set, the loader determines the path of the current load
module when the loader first encounters $ORIGIN,
whether it is in LD_LIBRARY_PATH,
SHLIB_PATH, RUNPATH,
or the shared library name in the shared library list.
To add $ORIGIN to the environment
variables LD_LIBRARY_PATH or SHLIB_PATH,
just place $ORIGIN in the value
of these environment variables. To add $ORIGIN
to the RUNPATH, use the linker
options +b or -L.
To add $ORIGIN to the path of a
shared library in the shared library list, use the linker option
+origin.
+origin -lx
or
+origin shared_library_name
(You can only use the +origin option before the -l option
or the name of a shared library.) The option causes the linker
to add $ORIGIN before the shared library name in the shared library
list and set the DF_ORIGIN flag for the output module. At runtime,
the dynamic loader determines the directory of the parent module
(object module, shared library, or executable) and replaces $ORIGIN
for that directory name. For example,
$ ld main.o +origin libx.so -L -lc
| NOTE | While the +origin option is available, the recommended way to specify
$origin is in the embedded path with the +b
option. For example, |
You might want to force immediate binding - that is, force all routines and data to be bound at startup time. With immediate binding, the overhead of binding occurs only at program startup, rather than across the program's execution. One possibly useful characteristic of immediate binding is that it causes any possible unresolved symbols to be detected at startup time, rather than during program execution. Another use of immediate binding is to get better interactive performance, if you don't mind program startup taking a little longer.
To force immediate binding, link an application with the -B immediate
linker option. For example, to force immediate binding of all symbols
in the main program and in all shared libraries linked with it,
you could use this ld
command:
$ ld -B prog.o -lc
The linker also supports nonfatal binding,
which is useful with the -B immediate
option. Like immediate binding, nonfatal immediate binding causes
all required symbols to be bound at program startup. The main difference
from immediate binding is that program execution continues even
if the dynamic loader cannot resolve symbols. Compare
this with immediate binding, where unresolved symbols cause the
program to abort.
To use nonfatal binding, specify the -B nonfatal
option along with the -B immediate
option on the linker command line. The order of the options is not
important, nor is the placement of the options on the line. For
example, the following ld
command uses nonfatal immediate binding:
$ ld prog.o -B nonfatal -B immediate -lc
Note that the -B nonfatal
modifier does not work with deferred binding
because a symbol must have been bound by the time a program actually
references or calls it. A program attempting to call or access a
nonexistent symbol is a fatal error.
The linker also supports restricted binding,
which is useful with the -B deferred
and -B nonfatal
options. The -B restricted
option causes the dynamic loader to restrict the search for symbols
to those that were visible when the library was loaded. If the dynamic
loader cannot find a symbol within the restricted set, a run-time
symbol binding error occurs and the program aborts.
The -B nonfatal
modifier alters this behavior slightly: If the dynamic loader cannot
find a symbol in the restricted set, it looks in the global symbol
set (the symbols defined in all libraries)
to resolve the symbol. If it still cannot find the symbol, then
a run-time symbol-binding error occurs and the program aborts.
When is -B restricted
most useful? Consider a program that creates duplicate symbol definitions
by either of these methods:
The program uses shl_load
with the BIND_FIRST
flag to load a library that contains symbol definitions that are
already defined in a library that was loaded at program startup.
The program calls shl_definesym
to define a symbol that is already defined in a library that was
loaded at program startup.
If such a program is linked with -B immediate,
references to symbols will be bound at program startup, regardless
of whether duplicate symbols are created later by shl_load
or shl_definesym.
But what happens when, to take advantage of the performance
benefits of deferred binding, the same program is linked with -B deferred?
If a duplicate, more visible symbol definition is created prior
to referencing the symbol, it binds to the more visible definition,
and the program might run incorrectly. In such cases, -B restricted
is useful, because symbols bind the same way as they do with -B immediate,
but actual binding is still deferred.
The linker supports the -B symbolic
option which optimizes call paths between procedures when building
shared libraries. It does this by building direct internal call
paths inside a shared library. In linker terms, import
and export stubs are bypassed for calls within
the library.
A benefit of -B symbolic
is that it can help improve application performance and the resulting
shared library will be slightly smaller. The -B symbolic
option is useful for applications that make a lot of calls between
procedures inside a shared library and
when these same procedures are called by programs outside of the
shared library.
| NOTE | The |
For example, to optimize the call path between procedures
when building a shared library called lib1.s,
use -B symbolic
as follows:
$ ld -B symbolic -b func1.o func2.o -o lib1.s
| NOTE | The Since all internal calls inside the shared library are resolved
inside the shared library, user-supplied modules with the same name
are not seen by routines inside the library. For example, you could
not replace internal |
Similar to the -h (hide symbol) and +e
(export symbol) linker options, -B symbolic optimizes call paths
in a shared library. However, unlike -h
and +e, all functions in a shared
library linked with -B symbolic
are also visible outside of the shared library.
Suppose you have two functions to place in a shared library. The convert_rtn() calls gal_to_liter().
Build the shared library with -b. Optimize the call path inside the shared library with -B symbolic.
$ ld -B symbolic -b convert.o volume.o -o libunits.s
Two main programs link to the shared library. main1 calls convert_rtn() and main2 calls gal_to_liter().
$ cc -Aa main1.c libunits.s -o main1 $ cc -Aa main1.c libunits.s -o main2
Figure 4: Symbols inside a Shared Library Visible with -B symbolic shows that a direct call path is established between convert_rtn() and gal_to_liter() inside the shared library. Both symbols are visible to outside callers.

The -h (hide symbol) and +e
(export symbol) options can also optimize the call path in a shared
library for symbols that are explicitly hidden. However, only the
exported symbols are visible outside of the shared library.
For example, you could hide the gal_to_liter
symbol as shown:
$ ld -b convert.o -h gal_to_liter volume.o -o libunits.s
or export the convert_rtn symbol:
$ ld -b +e convert_rtn convert.o volume.o -o libunits.s
In both cases, main2 will not be able to resolve its reference
to gal_to_liter() because only the convert_rtn()
symbol is exported as shown below inFigure 5: Symbol hidden in a Shared Library:

If both an archive and shared version of a particular library
reside in the same directory, ld
links with the shared version. Occasionally, you might want to override
this behavior.
As an example, suppose you write an application that will run on a system on which shared libraries may not be present. Since the program could not run without the shared library, it would be best to link with the archive library, resulting in executable code that contains the required library routines. See also Caution When Mixing Shared and Archive Libraries .
The -a
option tells the linker what kind of library to link with. It applies
to all libraries (-l
options) until the end of the command line or until the next -a
option. Its syntax is:
-a {archive | shared | default | archive_shared | shared_archive}
The different option settings are:
-a archiveSelect archive libraries. If the archive library
does not exist, ld
generates an error message and does not generate the output file.
-a sharedSelect shared libraries. If the shared library does
not exist, ld
generates an error message and does not generate the output file.
-a defaultThis is the same as -a shared_archive.
-a archive_sharedSelect the archive library if it exists; otherwise,
select the shared library. If the library cannot be found in either
version, ld generates
an error message and does not generate the output file.
-a shared_archiveSelect the shared library if it exists; otherwise,
select the archive library. If the library cannot be found in either
version, ld generates
an error message and does not generate the output file.
The -a shared
and -a archive
options specify only one type of library to use. An error results
if that type is not found. The other three options specify a preferred
type of library and an alternate type of library if the preferred
type is not found.
| CAUTION | You should avoid mixing shared libraries and archive libraries in the same application. For more information see Caution When Mixing Shared and Archive Libraries . |
The following command links with the archive versions of libcurses,
libm and libc:
$ ld /usr/ccs/lib/hpux32/crt0.o prog.o -a archive -lcurses -lm -lc
Use the -dynamic option to
instruct the linker to look for shared libraries first and then
archive libraries. The linker outputs a share-bound executable.
This option is on by default .
For example:
$ld main.o -dynamic -L. -lbar -lc
is the same as:
ld main.o -L. -lbar -k
If you specified an archive library, the linker links it in, but the resulting executable is still a share-bound executable. This is true even if the linker finds no shared libraries at link time.
Use the -noshared option
if you need to link with all archive libraries. The linker outputs
an archive-bound executable.
| NOTE | You cannot link in shared libraries if you specify this option. |
In the following example, the linker only looks for
/usr/lib/hpux32/libfoo.a and /user/lib/hpux32/libc.a:
ld /usr/ccs/hpux32/crt0.o main.o -noshared -L. -lfoo -lc
If you specify a shared library libbar.so with this option, the linker emits an error message.
ld: The shared library "libbar.so" cannot be processed in a static link. Fatal error.
The +e
option allow you to hide and export symbols. Exporting
a symbol makes the symbol a global definition, which can be accessed
by any other object modules or libraries. The +e
option exports symbol and hides from
export all other global symbols not specified with +e.
In essence, -h
and +e provide
two different ways to do the same thing.
The syntax of the +e
option is:
+e symbol
Suppose you want to build a shared library from an object
file that contains the following symbol definitions as displayed
by the nm command:
$ nm -p sem.o 0000000000 U $global$ 1073741824 d $THIS_DATA$ 1073741864 b $THIS_BSS$ 0000000004 cS sem_val 0000000000 T check_sem_val 0000000036 T foo 0000000000 U printf 0000000088 T bar 0000000140 T sem
In this example, check_sem_val,
foo, bar,
and sem are all
global definitions. To create a shared library where check_sem_val
is a hidden, local definition, you could use either of the following
commands:
$ ld -b -h check_sem_val sem.o -o libsem.so One -h option. $ ld -b +e foo +e bar +e sem sem.o -o libsem.so Three +e options.
In contrast, suppose you want to export only the check_sem_val
symbol. Either of the following commands would work:
$ ld -b -h foo -h bar -h sem sem.o -o libsem.so Three -h options. $ ld -b +e check_sem_val sem.o -o libsem.so One +e option.
How do you decide whether to use -h
or +e? In general,
use -h if you
simply want to hide a few symbols. And use +e
if you want to export a few symbols and hide a large number of symbols.
You should not combine -h
and +e options
on the same command line. For instance, suppose you specify +e sem.
This would export the symbol sem
and hide all other symbols. Any additional -h
options would be unnecessary. If both -h
and +e are used
on the same symbol, the -h
overrides the +e
option.
The linker command line could get quite lengthy and difficult
to read if several such options were specified. And in fact, you
could exceed the maximum HP-UX command line length if you specify
too many options. To get around this, use ld
linker option files, described under Passing Linker Options
in a file with -c . You can specify any number
of -h or +e
options in this file.
You can use -h
or +e options
when building a shared library (with -b), combining .o files ( with
-r), and when linking to create an a.out
file.
Like the +e option, the +ee
option allows you to export symbols. Unlike the +e
option, the option does not alter the visibility of any other symbols
in the file. It exports the specified symbol, and does not hide
any of the symbols exported by default.
In PA-32 mode, the linker exports from a program only those symbols
that were imported by a shared library. For example, if a shared
executable's libraries do not reference the
program's main
routine, the linker does not include the main
symbol in the a.out
file's export list. Normally, this is a problem only when a program
calls shared library management routines (described in Shared Library Management
Routines ). To
make the linker export all symbols from a program,
invoke ld with
the -E option.
In IPF/PA-64 mode, the behavior is specified by -E is
the default behavior. The +e
option allows you to be more selective about which symbols are exported,
resulting in better performance. For details on +e,
see Exporting Symbols with +e.
Use the +hideallsymbols option
to hide all symbols to prevent the linker from exporting them in
a shared link.
In the following example, main()
exports func() and test().
Using +hideallsymbols, the linker
does not export these two routines in the a.out.
ld main.o +hideallsymbols -L. -lfoo -lc
elfdump -t a.out
a.out: ... .symtab index Type Bind Other Sect Value Size Name 1 FUNC LOCL 0 0xb 0x4000000000001104 0 test ... 10 FUNC LOCL 0 0xb 0x4000000000001200 0 func
The -h
option allows you to hide symbols. Hiding
a symbol makes the symbol a local definition, accessible only from
the object module or library in which it is defined. Use -h
if you simply want to hide a few symbols.
You can use -h
option when building a shared library (with -b)
and when linking to create an a.out
file. When combining .o
files with -r,
you can use the -h
option.
The syntax of the -h
option is:
-h symbol
The -h
option hides symbol. Any other global
symbols remain exported unless hidden with -h.
Suppose you want to build a shared library from an object
file that contains the following symbol definitions as displayed
by the nm command:
$ nm -p sem.o 0000000000 U $global$ 1073741824 d $THIS_DATA$ 1073741864 b $THIS_BSS$ 0000000004 cS sem_val 0000000000 T check_sem_val 0000000036 T foo 0000000000 U printf 0000000088 T bar 0000000140 T sem
In this example, check_sem_val,
foo, bar,
and sem are all
global definitions. To create a shared library where check_sem_val
is a hidden, local definition, you could do the following:
$ ld -b -h check_sem_val sem.o
You should not combine -h
and +e options
on the same command line. For instance, suppose you specify +e sem.
This would export the symbol sem
and hide all other symbols. Any additional -h
options would be unnecessary. If both -h
and +e are used
on the same symbol, the -h
overrides the +e
option.
The linker command line could get quite lengthy and difficult
to read if several such options were specified. And in fact, you
could exceed the maximum HP-UX command line length if you specify
too many options. To get around this, use ld
linker option files, described under Passing Linker Options
in a file with -c . You can specify any number
of -h or +e
options in this file.
When building a shared library, you might want to hide a symbol in the library for several reasons:
It can improve performance because the dynamic loader does not have to bind hidden symbols. Since most symbols need not be exported from a shared library, hiding selected symbols can have a significant impact on performance.
It ensures that the definition can only be accessed by other routines in the same library. When linking with other object modules or libraries, the definition will be hidden from them.
When linking with other libraries (to create an executable), it ensures that the library will use the local definition of a routine rather than a definition that occurs earlier in the link order.
Exporting a symbol is necessary if the symbol must be accessible
outside the shared library. But remember that, by default, most
symbols are global definitions anyway, so it is seldom necessary
to explicitly export symbols. In C, all functions and global variables
that are not explicitly declared as static
have global definitions, while static
functions and variables have local definitions. In FORTRAN, global
definitions are generated for all subroutines, functions, and initialized
common blocks.
When using +e,
be sure to export any data symbols defined in the shared library
that will be used by another shared library or the program, even
if these other files have definitions of the data symbols. Otherwise,
your shared library will use its own private copy of the global
data, and another library or the program file will not see any change.
One example of a data symbol that should almost always be
exported from a shared library is errno.
errno is defined
in every shared library and program; if this definition is hidden,
the value of errno
will not be shared outside of the library.
The -r
option combines multiple .o
files, creating a single .o
file. The reasons for hiding symbols in a .o
file are the same as the reasons listed above for shared libraries.
However, a performance improvement will occur only if the resulting
.o file is later
linked into a shared library.
In PA-32 mode, the linker exports all of a program's global definitions
that are imported by shared libraries specified on the linker command
line. For example, given the following linker command, all global
symbols in crt0.o
and prog.o that
are referenced by libm
or libc are automatically
exported:
$ ld /usr/ccs/lib/crt0.o prog.o -lm -lc
With libraries that are explicitly loaded with shl_load,
this behavior may not always be sufficient because the linker does
not search explicitly loaded libraries (they aren't even present
on the command line). You can work around this using the -E
or +e linker
option.
As mentioned previously in the section Exporting Symbols from main with
-E , the -E
option forces the export of all symbols from
the program, regardless of whether they are referenced by shared
libraries on the linker command line. The +e
option allows you to be more selective in what symbols are exported.
You can use +e
to limit the exported symbols to only those symbols you want to
be visible.
For example, the following ld
command exports the symbols main
and foo. The
symbol main is
referenced by libc.
The symbol foo
is referenced at run time by an explicitly loaded library not specified
at link time:
$ ld /usr/ccs/lib/crt0.o prog.o +e main +e foo -lm -lc -ldld
When using +e,
be sure to export any data symbols defined in the program that may
also be defined in explicitly loaded libraries. If a data symbol
that a shared library imports is not exported from the program file,
the program uses its own copy while the shared library uses a different
copy if a definition exists outside the program
file. In such cases, a shared library might update a global variable
needed by the program, but the program would never see the change
because it would be referencing its own copy.
One example of a data symbol that should almost always be
exported from a program is errno.
errno is defined
in every shared library and program; if this definition is hidden,
the value of errno
will not be shared outside of the program in which it is hidden.
In IPF/PA-64 mode, the behavior specified by -E
is the default behavior.
A library can be moved even after an application has been
linked with it. This is done by providing the executable with a
list of directories to search at run time for any required libraries.
One way you can store a directory path list in the program is by
using the +b
path_list linker option.
Note that dynamic path list search works only for libraries
specified with -l
on the linker command line (for example, -lfoo).
It won't work for libraries whose full path name is specified (for
example, /usr/contrib/lib/libfoo.s).
However, it can be enabled for such libraries with the -l
option to the chatr
command (see Changing a Program's Attributes
with chatr(1) ).
The syntax of the +b
option is
+b path_list
where path_list is the list of
directories you want the dynamic loader to search at run time. For
example, the following linker command causes the path .:/app/lib::
to be stored in the executable. At run time, the dynamic loader
would search for libfoo.s,
libm.s, and
libc.s in the
current working directory (.),
the directory /app/lib,
and lastly in the location in which the libraries were found at
link time (::):
$ ld /opt/langtools/lib/crt0.o +b .:/app/lib:: prog.o -lfoo \ -lm -lc
If path_list is only a single colon,
the linker constructs a path list consisting of all the directories
specified by -L,
followed by all the directories specified by the LPATH
environment variable. For instance, the following linker command
records the path list as /app/lib:/tmp:
$ LPATH=/tmp ; export LPATH $ ld /opt/langtools/lib/crt0.o +b : -L/app/lib prog.o -lfoo \ -lm -lc
Whether specified as a parameter to +b
or set as the value of the SHLIB_PATH
environment variable, the path list is simply one or more path names
separated by colons (:), just like the syntax of the PATH
environment variable. An optional colon can appear at the start
and end of the list.
Absolute and relative path names are allowed. Relative paths are searched relative to the program's current working directory at run time.
Remember that a shared library's full path name is stored
in the executable. When searching for a library in an absolute or
relative path at run time, the dynamic loader uses only the basename
of the library path name stored in the executable. For instance,
if a program is linked with /usr/local/lib/libfoo.s,
and the directory path list contains /apps/lib:xyz,
the dynamic loader searches for /apps/lib/libfoo.sl,
then ./xyz/libfoo.s.
The full library path name stored in the executable is referred
to as the default library path. To cause the dynamic loader to search
for the library in the default location, use a null directory path
(). When the
loader comes to a null directory path, it uses the default shared
library path stored in the executable. For instance, if the directory
path list in the previous example were /apps/lib::xyz,
the dynamic loader would search for /apps/lib/libfoo.s,
/usr/local/lib/libfoo.s,
then ./xyz/libfoo.s.
If the dynamic loader cannot find a required library in any
of the directories specified in the path list, it searches for the
library in the default location ()
recorded by the linker.
Note that dynamic path list search works only for libraries
specified with -l
on the linker command line (for example, -lfoo).
It won't work for libraries whose full path name is specified (for
example, /usr/contrib/lib/libfoo.s).
However, it can be enabled for such libraries with the -l
option to the chatr
command (see Changing a Program's Attributes
with chatr(1) ).
A library can be moved even after an application has been
linked with it. Linking the program with +s,
enables the program to use the path list defined by the SHLIB_PATH
environment variable at run time.
When a program is linked with +s,
the dynamic loader will get the library path list from the SHLIB_PATH
environment variable at run time. This is especially useful for
application developers who don't know where the libraries will reside
at run time. In such cases, they can have the user or an install
script set SHLIB_PATH
to the correct value.
The Path List provides additional details about
the path list to SHLIB_PATH.
Moving Libraries after Linking with +b provides another way to move libraries.
Use the +noenvvar to instruct
the dynamic loader not to look at the environment variables relating
to dynamic path searching at runtime. It ignores LD_LIBRARY_PATH
and SHLIB_PATH environment variables.
This option is on by default in with ld +compat.
It is off by default with ld +std.
For example, if libbar.so
has dependent library libfee.so
that is ./ at link time, but is
moved to /tmp by runtime:
ld main.o -L. -lbar -lc export LD_LIBRARY_PATH=/tmp mv libbar.so /tmp a.out called bar() called fee() mv /tmp/libbar.so ./ ld main.o +noenvvar -L. -lbar -lc mv libbar.so /tmp a.out dld.so: Unable to find library "libbar.so"
Use the +[no]forceload option
to control how the linker loads object files from an archived library.
+forceload instructs the linker
to load all object files from an archive library. +noforceload
tells the linker to only load those modules from an archive library
that is needed. The mode you select, either by default or explicitly,
remains on until you change it.
+noforceload is the default.
In the following example, main()
references foo(), which is a module
in mylib.a. The function foo()
doesn't reference any other module in mylib.a
and libc.a. If mylib.a
contains foo.o and bar.o,
then only foo.o is linked in.
ld /usr/ccs/lib/hpux32/crt0.o main.o +vtype libraries mylib.a -lc
... Selecting mylib.a[foo.o] to resolve foo
ld /usr/ccs/lib/hpux32/crt0.o main.o +forceload mylib.a -lc\ +vtype libraries
... Selecting mylib.a[foo.o] to forcibly load Selecting mylib.a[bar.o] to forcibly load
The -c
file option causes the linker to read
command line options from the specified file.
This is useful if you have many -h
or +e options
to include on the ld
command line, or if you have to link with numerous object files.
For example, suppose you have over a hundred +e
options that you need when building a shared library. You could
place them in a file named eopts
and force the linker to read options from the file as follows:
$ ld -o libmods.s -b -c eopts mod*.o $ cat eopts Display the file. +e foo +e bar +e reverse_tree +e preorder_traversal +e shift_reduce_parse . . .
Note that the linker ignores lines in that option file that
begin with a pound sign (#).
You can use such lines as comment lines or to temporarily disable
certain linker options in the file. For instance, the following
linker option file for an application contains a disabled -O
option:
# Exporting only the "compress" symbol resulted # in better run-time performance: +e compress # When the program is debugged, remove the pound sign # from the following optimization option: # -O
If you use certain linker options all the time, you may find
it useful to specify them in the LDOPTS
environment variable. The linker inserts the value of this variable
before all other arguments on the linker command line. For instance,
if you always want the linker to display verbose information (-v)
and a trace of each input file (-t),
set LDOPTS as
follows:
$ LDOPTS="-v -t" Korn and Bourne shell syntax. $ export LDOPTS
Thereafter, the following commands would be equivalent:
$ ld -u main prog.o -lc $ ld -v -t -u main prog.o -lc
To direct the linker to search a particular library, use the
-lname
option. For example, to specify libc,
use -lc; to specify
libm, use -lm;
to specify libXm,
use -lXm.
When writing programs that call routines not found in the
default libraries linked at compile time, you must specify the libraries
on the compiler command line with the -lx
option. For example, if you write a C program that calls POSIX math
functions, you must link with libm.
The x argument corresponds to the
identifying portion of the library path name - the part
following lib
and preceding the suffix .a
or .s. For example,
for the libm.s
or libm.a library,
x is the letter m:
$ cc -Aa mathprog.c -lm
The linker searches libraries in the order in which they are
specified on the command line (that is, the link order).
In addition, libraries specified with -l
are searched before the libraries that the
compiler links by default.
The -l:
option works just like the -l
option with one major difference: -l:
allows you to specify the full basename of the library to link with.
For instance, -l:libm.a
causes the linker to link with the archive library /usr/lib/hpux32/libm.a,
regardless of whether -a shared
was specified previously on the linker command line.
The advantage of using this option is that it allows you to
specify an archive or shared library explicitly without having to
change the state of the -a
option. (See also Caution When Mixing
Shared and Archive Libraries .)
For instance, suppose you use the LDOPTS
environment variable (see Passing Linker Options
with LDOPTS ) to set the -a
option that you want to use by default when linking. And depending
on what environment you are building an application for, you might
set LDOPTS to
-a archive or
-a shared. You
can use -l: to
ensure that the linker will always link with a particular library
regardless of the setting of the -a
option in the LDOPTS
variable.
For example, even if LDOPTS
were set to -a shared,
the following command would link with the archive libfoo.a
in the directory /usr/mylibs,
the archive libm.a
and libc.a:
$ ld /usr/ccs/lib/hpux32/crt0.o -u main prog.o -L/usr/mylibs \
-l:libfoo.a -l:libc.a -l:libm.a
Use the +allowunsats option
to instruct the linker to not flag unsatisfied symbols at link time.
This is the default for relocatable (-r)
and shared library builds (-b),
and is the default behavior in PA-32 mode.
Use the +noallowunsat option
to instruct the linker to flag as an error any unsatisfied symbol
in the resulting output file. The linker still creates a.out,
but the file does not have any execute permission bits set. This
is the default for program files (same behavior as in PA-32 mode).
For example, where main()
references functions foo() and bar().
bar() resides in libbar.so
and foo() resides in libfoo.so
ld main.o +allowunsats -L. -lbar -lc
ld: (warning) Unsatisfied symbol "foo". 1 warning.
+allowunsats still causes
the linker to emit a warning message and output a.out.
If you do not specify the option and the linker finds an unsatisfied
symbol, the linker emits an error message and a non-executable a.out.
ld main.o -L. -lbar -lc
ld: Unsatisfied symbol "foo". 1 error.
The a.out
file created by the linker contains symbol table, relocation, and
(if debug options were specified) information used by the debugger.
Such information can be used by other commands that work on a.out
files, but is not actually necessary to make the file run. ld
provides two command line options for removing such information
and, thus, reducing the size of executables:
-sStrips all such information from the file. The executable
becomes smaller, but difficult or impossible to use with a symbolic
debugger. You can get much the same results by running the strip
command on an executable (see strip(1)).
In some cases, however, -s
rearranges the file to save more space than strip.
-xStrips only local symbols from the symbol table. It reduces executable file size with only a minimal affect on commands that work with executables. However, using this option may still make the file unusable by a symbolic debugger.
These options can reduce the size of executables dramatically. Note, also, that these options can also be used when generating shared libraries without affecting shareability.
Use the +stripunwind option
to suppress output of the unwind table.
ld -b foo.o -o libfoo.s +stripunwind elfdump -U libfoo.s
libfoo.s:
In the HP-UX 11.0 release, the linker toolset supports extended features for linking in PA-64 mode. Since compatibility with the previous linker toolset is a high priority, the IPF linker uses much of the old behavior in the new toolset. The IPF linker includes two options to allow you to instruct the linker to link in one of two modes:
Compatibility mode, with the +compat
option, to create a link and operation in PA-32 style. Because of
some object file format restrictions, the mode is not completely
compatible with the style of the PA-32 linker.
Standard mode, with the +std
option, set by default in the IPF linker, to create a link and
load operation in PA-64 style. This mode uses the new behaviors
and features of the PA-64 linker.
The +compat option instructs the linker to do a PA-32 link.
When you use the +compat
option, the linker:
Uses PA-32 shared library internal name processing.
Lists all dependent shared libraries in a DT_HP_NEEDED
entry the dynamic table using the PA-32 shared library naming conventions.
These dependent libraries are recorded as compatibility mode libraries
even if they are really created as standard mode dependent libraries.
Does not use embedded paths at link time to find dependent libraries.
Considers the order of ld +b
and +s.
+b
first means dld looks at the RPATH
first when searching for dependent shared libraries.
To get the default RPATH,
you must specify ld +b. This instructs
the linker to construct a default RPATH
consisting of the -L directories
and LPATH.
+s first means
the dynamic loader looks at the SHLIB_PATH
environment variable first when searching for dependent shared libraries.
You must specify ld +s to
force the dynamic loader to use SHLIB_PATH
to search for shared libraries at runtime.
At runtime, the dynamic loader does a PA-32 load for all compatibility mode dependent shared libraries. The dynamic loader:
Does dynamic path searching for compatibility-mode
dependent shared libraries that have the dynamic path selected (set
in the DT_HP_NEEDED entry if the
shared library was specified with -l).
Uses SHLIB_PATH
only if you specify ld +s (or chatr +s)
for compatibility-mode shared libraries.
Allows RPATH inheritance
from ancestors to children when searching for dependent compatibility-mode
shared libraries specified with ld -l.
This is only allowed in an a.out
that was linked with +compat. If
the a.out was linked +std,
no library (even a compatibility mode shared library) uses embedded
RPATH inheritance.
Allows dynamic path searching on shared libraries
loaded by shl_load routines, if
the DYNAMIC_FLAG is passed to shl_load().
Does a depth-first search of all compatibility-mode dependent libraries.
Looks at RPATH
or SHLIB_PATH first, depending
on the ld +b/+s
ordering for all ld -l dependent
shared libraries. The dynamic loader looks at whichever has second
precedence next, and then looks for the shared library as specified
in the dynamic load entry.
Looks for the dynamic table entry as if the dynamic path bit is not set.
The +std option instructs
the linker to do a standard mode PA-64 link. This is currently the
default.
This default may change in future releases.
When you use +std, the linker:
Assumes -dynamic
was passed to ld. The linker looks
for shared libraries first. The output executable is a shared executable.
All dependent shared libraries are output in the
dynamic table in a DT_NEEDED entry.
These dependent shared libraries are recorded as standard mode shared
libraries.
ld +b and +s
ordering is ignored. ld +s is on
by default.
Uses de facto standard internal name processing for dependent shared libraries.
Uses embedded RPATHs
at link time to find dependent shared libraries.
If you do not specify ld +b, the linker uses a default
RPATH consisting of the -L
directories, LPATH, and the default
directories /usr/lib/hpux32:/usr/ccs/lib/hpux32
for 32-bit applications and /usr/lib/hpux64:/usr/ccs/lib/hpux64
for 64-bit applications.
At runtime, the dynamic loader does a PA-64 load for all standard mode dependent shared libraries. The dynamic loader:
Does dynamic path searching only for
standard-mode shared libraries in the DT_NEEDED
entry of the dynamic table which do not contain a path. For those
standard-mode dynamic libraries that contain paths, dld
looks for the library as specified.
Looks for the shared library as specified in the
DT_NEEDED dynamic table entry if
it contains a path.
Looks at LD_LIBRARY_PATH
and SHLIB_PATH environment variables
at runtime by default when doing dynamic path searching for standard-mode
shared libraries.
Does not allow RPATH
inheritance from ancestors to children (only allowed from parent
to child).
Does a breadth-first search for all standard-mode dependent shared libraries.
Looks at the environment variables first, followed
by RPATH, and the default directories
by default when doing dynamic path searching for standard-mode dependent
shared libraries.
Use the +std option to instructs
the linker to do a PA-64 link. This is the default mode. For more
information, see Using
the IPF Linker with +compat or +std.
Use the +compat option to
instruct the linker to do a PA-32 link. For more information, see
Using
the IPF Linker with +compat or +std.
The linker automatically maps sections from input object files
onto output segments in executable files. These options to the ld
command allow you to change the linker's default mapping.
Use the -k filename option
to provide a memory map. The linker uses the file specified by filename
as the output file memory map.
The +nodefaultmap option
used with -k option prevents the
linker from concatenating the default memory map to the map provided
by filename. If you specify +nodefaultmap,
the linker does not append the default mapfile to your mapfile.
If you do not specify +nodefaultmap
with -k, the linker appends the
output file to the default mapfile.
| NOTE | In most cases, the linker produces a correct executable without the use of the mapfile option. The mapfile option is an advanced feature of the linker toolset intended for systems programming use, not application programming use. When using the mapfile option, you can create executable files that do not execute. |
For more information on mapfiles and examples using these options, see Using Mapfiles.
Use the +vtype option to
get verbose output about specified elements of the link operation.
The following values specify the type:
Description
files Dump information about each object file loaded.
ld main.o +vtype files -L. -lfile1 -lfile2 -lc Loading main.o: Loading ./libfile1.so: Loading ./libfile2.so: Loading /usr/lib/hpux32/libc.so: Loading /usr/lib/hpux32/libdl.so.1:
libraries Dump information about libraries searched.
ld main.o +vtype libraries -L. -lfile1 -lfile2 -lc Searching /usr/lib/hpux32/libc.a: Selecting /usr/lib/hpux32/libc.a
sections Dump information about each input section added to the output file.
ld main.o +vtype sections -L. -lfile1 -lfile2 -lc
main.o:
section .note NOTE 240 4 added to note segment
section .note NOTE 48 4 added to note segment
section .IA_64.unwind_info PROGBITS A 28 4
added to text segment
section .text PROGBITS AX 112 16 added to text
segment
section .IA_64.unwind UNWIND A 12 4 added to
text segment
section .rodata PROGBITS A 9 8 added to text
segment
section .HP.opt_annot PROGBITS A 25 8 added to
text segment
symbols Dump information about global symbols referenced/defined from/in the input files.
ld main.o +vtype symbols -L. -lfile1 -lfile2 -lc main.o: main is DEFINED GLOBAL FUNC printf is UNDEF GLOBAL FUNC lib1_func is UNDEF GLOBAL FUNC lib2_func is UNDEF GLOBAL FUNC ./libfile1.so: printf is UNDEF GLOBAL FUNC _DYNAMIC is DEFINED GLOBAL OBJECT lib1_func is DEFINED GLOBAL FUNC ...
allDump all of the above. Same as -v.
ld main.o +vtype all -L. -lfile1 -lfile2 -lc
Loading main.o:
main.o:
main is DEFINED GLOBAL FUNC
printf is UNDEF GLOBAL FUNC
lib1_func is UNDEF GLOBAL FUNC
lib2_func is UNDEF GLOBAL FUNC
main.o:
section .note NOTE 240 4 added to note segment
section .note NOTE 48 4 added to note segment
section .IA_64.unwind_info PROGBITS A 28 4
added to text segment
section .text PROGBITS AX 112 16 added to text
segment
section .IA_64.unwind UNWIND A 12 4 added to
text segment
section .rodata PROGBITS A 9 8 added to text
segment
section .HP.opt_annot PROGBITS A 25 8 added to
text segment
Loading ./libfile1.so:
./libfile1.so:
...
procelim Dump information about the sections that have been
rejected by the +oprocelim option.
ld main.o +Oprocelim +vtype procelim -L. -lfile1 -lfile2 Deleting 236 bytes in section file.note Eliminated 0K of dead code and data, 0 global, 0 local and 0 hidden symbols
This chapter describes the linker toolset, which provides several tools to help you find symbols, display and modify object files, and determine link order. These tools are specific to ELF object file type.
The following table lists the linker toolset.
| Tool | Description |
|---|---|
|
Displays or |