This section describes linker commands for the 32-bit and 64-bit linker.
Note Unless otherwise noted, all examples show 32-bit behavior.
Linking with the crt0.o Startup File
In default mode, you need not 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 need not include the crt0.o
startup file on the ld command line for shared bound links.
The dynamic loader does some of the startup duties previously done by
crt0.o .
See The crt0.o Startup File, and
crt0(3) manpage for more information.
Changing the Default
Library Search Path with -L, LPATH, and $ORIGIN
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.
Overriding the Default Linker Search
Path with LPATH
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 must contain a list of colon-separated
directory path names that ld must 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
Augmenting the Default Linker Search
Path with -L
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 .
Augmenting the Default Linker Search
Path with +origin
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 applies to the shared library specified
directly afterwards, for example, libc.so or -lc .
At runtime, if the dynamic loader cannot find the library listed 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
Using $ORIGIN
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 , 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 use only 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
You can use $ORIGIN in SHLIB_PATH/LD_LIBRARY_PATH only for programs on PA32 systems.
While the +origin option is available, the recommended way to specify
$origin is in the embedded path with the +b
option. For example,
$ ld main.o -lc +b $ORIGIN
If you use +b,\$ORIGIN; the $ORIGIN only affects libraries that
are subject to dynamic path lookup;
that is, the library shared_library_name
is specified with -l or with no embedded
/ character. If you use +origin shared_library_name,
the library is located using $ORIGIN,
which is recorded in the full library name.
Changing the Default
Shared Library Binding with -B
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 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,
but in this case the program startup may take a little longer.
Example Using -B immediate
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 can
use this ld command:
$ ld -B immediate prog.o -lc
Nonfatal Shared Library Binding with
-B nonfatal
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 be 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.
Restricted Shared Library Binding with
-B restricted
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 are 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 may run incorrectly. In such cases, -B restricted
is useful, because symbols bind the same way as they do with -B
immediate , but the actual binding is still deferred.
Direct Shared Library Binding with
-B direct
The linker also supports direct binding, which creates
a direct link between symbol references and shared libraries by recording
the name of the resolved shared library during symbol resolution. This
information is used during runtime to quickly resolve symbols without
searching through all currently-loaded libraries.
The -B direct option implicitly
turns on symbolic binding and disables dependent shared library processing.
Direct binding can be disabled during runtime by setting the LD_NODIRECTBIND
environment variable.
Shared Library Binding with -B
group
Group binding marks the shared library so that it behaves as if loaded
with RTLD_GROUP flag to dlopen() . This does
not affect the dependent shared libraries.
NoteYou can use the libraries built with the -B group option only with
the dld.sl in version B.11.37 or later.
Lazydirect Shared Library Binding with
-B lazydirect
Lazydirect binding only records direct bind information to shared libraries
that are marked for lazy loading. See +[no]lazyload .
Shared Library Binding with -B nodelete
Nodelete binding marks the shared library so that an explicit unload
using dlclose or shl_load returns success silently
without detaching the shared library from the process. Subsequently, the
shared library handle is valid only for shl_findsym . It stays
invalid for dlsym , dlclose , and shl_unload until
the next explicit load using shl_load or dlopen .
NoteYou can use the libraries built with the -B nodelete option only with
the dld.sl in version B.11.37 or later.
-B nodirect
Nodirect binding precludes direct binding. Only a "direct hint"
is recorded for references to libraries marked for lazy loading. This
is the default behavior.
Improving Shared Library Performance
with -B symbolic
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.
The benefit of using -B symbolic option is that it helps improve application
performance and the resulting shared library is 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 -B symbolic option applies only to function references in a shared library.
Example Using -B symbolic
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 +e option overrides the -B symbolic option.
For example, when you use +e symbol, only symbol
is exported and all other symbols are hidden. Similarly, if
you use +ee symbol, only symbol is
exported, but other symbols exported by default remain visible.
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 cannot
replace internal libc.sl malloc() calls with your own version
of malloc() if libc.sl was linked with -B
symbolic .
Comparing -B symbolic with -h and +e
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.
Case 1: Building a Shared Library with
-B symbolic
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.sl
-
Two main programs link to the shared library. The main1 calls convert_rtn()
and main2 calls gal_to_liter().
$ cc -Aa main1.c libunits.sl -o main1
$ cc -Aa main2.c libunits.sl -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.
Figure 4: Symbols Inside a Shared Library Visible with -B symbolic
Case 2: Building a Shared Library with -h or +e
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 can hide the gal_to_liter
symbol, as shown:
$ ld -b convert.o -h gal_to_liter volume.o -o libunits.sl
or export the convert_rtn symbol:
$ ld -b +e convert_rtn convert.o volume.o -o libunits.sl
In both cases, main2 cannot to resolve its reference to gal_to_liter()
because only the convert_rtn() symbol is exported, as shown
below in Figure 5: Symbol Hidden in a Shared Library:
Figure 5: Symbol Hidden in a Shared Library
Choosing Archive
or Shared Libraries with -a
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 runs on a system
on which shared libraries may not be present. Since the program cannot 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 .
Option Settings to -a
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 archive
-
Select archive libraries. If the archive library does not exist,
ld generates an error message and does not generate the output
file.
-a shared
-
Select shared libraries. If the shared library does not exist, ld
generates an error message and does not generate the output file.
-a default
-
This is the same as -a shared_archive .
-a archive_shared
-
Select the archive library if it exists; otherwise, select the shared
library. If the library is not found in either version, ld
generates an error message and does not generate the output file.
-a shared_archive
-
Select the shared library if it exists; otherwise, select the archive
library. If the library is not 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 must avoid mixing shared libraries and archive libraries in the
same application. For more information, see Caution
When Mixing Shared and Archive Libraries .
Example Using -a
The following command links with the archive versions of libcurses ,
libm , and libc :
$ ld /opt/langtools/lib/hpux32/crt0.o prog.o -a archive -lcurses -lm -lc
Linking Shared Libraries with -dynamic
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 -lc
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.
Linking Archived Libraries with -noshared
Use the -noshared option if you need to link with all archive
libraries. The linker outputs an archive-bound executable.
NoteYou 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 displays the error message:
ld: The shared library "libbar.so" cannot be processed in a static link.
Fatal error.
Exporting Symbols with +e
The +e option allows you to hide and export symbols. Exporting
a symbol makes the symbol a global definition, which can be accessed by
other object modules or libraries. The +e option exports the
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
Example Using +e
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 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.
When to use -h versus +e
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 must not run -h and +e options on
the same command line. For instance, suppose you specify +e sem .
This exports the symbol sem and hides all other symbols.
Any additional -h options becomes unnecessary. If both -h
and +e are used on the same symbol, the -h overrides
the +e option.
The linker command line gets lengthy and difficult to read
if several such options are specified. In fact, you 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.
Exporting Symbols with +ee
Like the +e option, the +ee option allows
you to export symbols. However, this option, the option does
not alter the visibility of other symbols in the file. It exports
the specified symbol, and does not hide any of the symbols exported by
default.
Exporting Symbols from main with -E
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 more information on +e , see Exporting Symbols with +e.
Hiding Symbols from Export with +hideallsymbols
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() . If you use +hideallsymbols , the linker
cannot export the following 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
Hiding Symbols with -h
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 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. Other global
symbols remain exported unless hidden with -h .
Example Using -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 can
do the following:
$ ld -b -h check_sem_val sem.o
Tips on Using -h
You must not run -h and +e options on
the same command line. For instance, suppose you specify +e sem .
This exports the symbol sem and hides all other symbols.
Additional -h options becomes unnecessary. If both -h
and +e are used on the same symbol, the -h overrides
the +e option.
The linker command line gets lengthy and difficult to read
if several such options are specified. In fact, you 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.
Hiding and Exporting Symbols When Building
a Shared Library
When building a shared library, you may want to hide a symbol in the
library for the following reasons:
Hiding a symbol 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.
Hiding a symbol 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 is hidden from them.
When linking with other libraries (to create an
executable), hiding a symbol ensures that the library uses 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 not 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 is used by another shared library or the
program, even if these other files have definitions of the data symbols.
Otherwise, your shared library uses its own private copy of the global
data, and another library or the program file cannot see any change.
One example of a data symbol that must be exported from
a shared library is errno . The errno data symbol is defined
in every shared library and program; if this definition is hidden, the
value of errno is not be shared outside of the library.
Hiding Symbols when Combining .o
Files with the -r Option
The -r option combines multiple .o files,
creating a single .o file. The reasons for hiding symbols
in an .o file are the same as the reasons listed above for
shared libraries. However, a performance improvement occurs only if
the resulting .o file is later linked into a shared library.
Hiding and Exporting Symbols when
Creating an a.out File
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 may update a global variable needed
by the program, but the program would never see the change because it
is referencing its own copy.
One example of a data symbol that should almost always be exported from
a program is errno . The errno data symbol is defined in every
shared library and program; if this definition is hidden, the value of
errno is not shared outside of the program in which
it is hidden.
In IPF/PA-64 mode, the behavior specified by -E is the
default behavior.
Not Recording Link Time Paths with +nodefaultrapth
By default, the linker records the link time paths of dependent shared libraries in the resultant
executables and shared libraries. In 32-bit mode, link time paths are recorded as a part of the
library name in the shared library list. In 64-bit mode, link time paths are recorded as
embedded path (unless embedded path is defined explicitly using +b option).
The linker can be told not to record any link time paths by specifying the
+nodefaultrpath option at link time. This option applies only to libraries specified with
-l on the linker command line (for example, -lfoo). Link time paths will still be recorded
for libraries whose full path name is specified (for example, /usr/contrib/lib/libfoo.sl) on the link line.
By default (i.e., if no other paths are specified) the 32 bit dld.sl searches for libraries
in the current directory and the 64 bit dld.sl searches in the /lib/pa20_64 and
/usr/lib/pa20_64 directories.
So if +nodefaultrpath is specified at link time and the application needs libraries that
are not present in above paths, care must be taken to provide the paths of these
libraries using either SHLIB_PATH, LD_LIBRARY_PATH or embedded path.
Moving Libraries after Linking
with +b
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 does not work for libraries whose full path name is specified (for example,
/usr/contrib/lib/libfoo.sl ). 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) ).
Specifying a Path List with +b
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 searches for libfoo ,
libm , and libc in the current working directory
(. ), and then in the directory /app/lib
$ 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
On PA32 systems, if multiple +b options appear on the link line, the output file records
the +b option that is specified first. On PA64 systems and Itanium-based systems, the output file records
the +b option that is specified last.
On PA32 systems, double colon (::) refers to the location in which the libraries were found
at link time. For example, the following linker command instructs the dynamic loader to search for libfoo,
libm, and libc first in the current working directory (.), then in 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
NoteThe double colon (::) feature is available only for PA32 systems.
The Path List
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 base name of the library path name stored
in the executable. For instance, if a program is linked with /usr/local/lib/libfoo.sl ,
and the directory path list contains /apps/lib:xyz , the dynamic
loader searches for /apps/lib/libfoo.sl , then ./xyz/libfoo.sl .
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 ().
NoteThe use of null directory path () is PA32 specific.
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 was /apps/lib::xyz , the dynamic loader searches
for /apps/lib/libfoo.sl , /usr/local/lib/libfoo.sl ,
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.
Moving Libraries After Linking with
+s and SHLIB_PATH
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.
Specifying a Path List with +s and
SHLIB_PATH
When a program is linked with +s , the dynamic loader
gets the library path list from the SHLIB_PATH environment
variable at run time. This is especially useful for application developers
who do not know where the libraries reside at run time. In such cases,
they can have the user or an install script set SHLIB_PATH
to the correct value.
For more information:
Ignoring Dynamic Path Environment Variables
with +noenvvar
Use the +noenvvar option to instruct the dynamic loader not to
look at the environment variables relating to dynamic path searching at
runtime. It ignores LD_LIBRARY_PATH, SHLIB_PATH ,
and $ORIGIN environment variables. This option is on by default
in PA32 mode and in programs linked with ld +compat . It is
off by default with ld +std .
For example, if libbar.so has dependent library libfee.so
that is found in ./ 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"
Controlling Archive Library Loading with
+[no]forceload
Use the +[no]forceload option to control how the linker
loads object files from an archived library. The +forceload instructs
the linker to load all object files from an archive library. The +noforceload
option instructs the linker to only load those modules from an archive library that
is needed. The mode you select, either by default or explicitly, remains
active until you change it.
The +noforceload option is the default.
In the following example, main() references foo() ,
which is a module in mylib.a . The function foo()
does not 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.
$ ld /opt/langtools/lib/hpux32/crt0.o main.o +vtype libraries mylib.a -lc
...
Selecting mylib.a[foo.o] to resolve foo
$ ld /opt/langtools/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
Passing Linker Options in
a file with -c
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 can place
them in a file named eopts and force the linker to read options
from the file as follows:
$ ld -o libmods.sl -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
Passing Linker Options
with LDOPTS
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
Specifying Libraries
with -l and -l:
To direct the linker to search a particular library, use the -l name
option. For example, to specify libc , use -lc ;
to specify libm , use -lm ; to specify libXm ,
use -lXm .
Specifying Libraries (-l)
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 -l x 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 .sl . For example, for the libm.sl
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.
Using the -l: option
The -l: option works just like the -l option
with one major difference: -l: allows you to specify the
full base name of the library to link with. For instance, -l:libm.a
causes the linker to link with the archive library /opt/langtools/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. Depending on what environment you are building
an application for, you may set LDOPTS to -a archive
or -a shared . You can use -l: to ensure that
the linker always links with a particular library regardless of the
setting of the -a option in the LDOPTS variable.
Example Using -l:
For example, even if LDOPTS were set to -a shared ,
the following command links with the archive libfoo.a
in the directory /usr/mylibs , the archive libm.a
and libc.a :
$ ld /opt/langtools/lib/hpux32/crt0.o -u main prog.o -L/usr/mylibs \
-l:libfoo.a -l:libc.a -l:libm.a
Flagging Unsatisfied Symbols with +[no]allowunsats
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() . The bar() resides in libbar
and foo() resides in libfoo
$ ld main.o +allowunsats -L. -lbar -lc
ld: (warning) Unsatisfied symbol "foo".
1 warning.
The +allowunsats option 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 displays an error message and a non-executable a.out.
$ ld main.o -L. -lbar -lc
ld: Unsatisfied symbol "foo".
1 error.
Stripping Symbol Table
Information from the Output File with -s and -x
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. The ld command provides two command line options for removing
such information and, thus, reducing the size of executables:
-s
-
Strips 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 .
-x
-
Strips only local symbols from the symbol table. It reduces
executable file size with only a minimal effect 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 drastically. Note,
also, that these options can also be used when generating shared libraries
without affecting shareability.
Controlling Output from the Unwind Table
with +strip unwind
Use the +stripunwind option to suppress output of the unwind
table.
$ ld -b foo.o -o libfoo.sl +stripunwind
$ elfdump -U libfoo.sl
libfoo.sl:
Using the IPF Linker with +compat or +std
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, on Itanium-based system the linker uses much of the old behavior
in the new toolset. The Itanium-based system linker includes two options to allow you to
instruct the linker to link in one of the following modes:
Compatibility mode, with the +compat
option, to create a link and operation in PA-32 mode. 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 linker on Itanium-based system, to create a link and load operation
in PA-64 mode. This mode uses the new behaviors and features of the PA-64
linker.
Using the Linker with +compat for
Compatibility Mode
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 .
-
The +b option 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 .
-
The +s option 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 a.out was
linked in standard mode with +std option, 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. Next, the dynamic loader
looks at whichever has second precedence, 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.
Using the Linker with +std for Standard
Mode
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.
The ld +b
and +s ordering is ignored. The ld +s option is on by default.
Uses de facto standard internal name processing
for dependent shared libraries.
Uses embedded RPATH s 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:/opt/langtools/lib/hpux32
for 32-bit applications and /usr/lib/hpux64:/opt/langtools/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.
Linking in PA-64 Mode with +std
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.
Linking in PA-32 Mode with +compat
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.
Changing Mapfiles with -k and +nodefaultmap
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.
Selecting Verbose Output with +vtype
Use the +vtype option to get verbose output about specified
elements of the link operation. The following values specify the type:
- Parameter
-
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
...
all
-
Dump 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
Turning on the linkage table protection with +protect
You can use the +protect option to turn on the linkage table protection mode. When you turn on this option,
the linker aligns the linkage table within page boundaries so that no other data resides in the same
page. During runtime, the pages containing the linkage table is marked READ_ONLY.
The +protect option turns on immediate binding. For more information about immediate binding, see
Changing the Default Shared Library Binding with -B.
The following options are not compatible with the +protect option:
- +mergeseg
- +filter
- +lazyload
Allocating Storage for Uninitialized Data with +nobss
When the loader loads a shared library, the loader must ensure that the data segment and bss are
mapped adjacent to each other in memory. This may involve repeated calls to mmap() and munmap().
When shared libraries are frequently loaded and unloaded, application performance may be affected.
You can use the new +nobss linker option to include the bss data of the shared
library in its data segment. When you build programs with the +nobss option, the number
of mmap and munmap calls at load time are minimal. However, the use of +nobss option
increases the disk size of the shared library. HP recommends the use of +nobss option only when the
frequent loading and unloading of shared libraries affect the application performance.
Initializing Floating Point Environment with +FP
You can use the +FP option to specify how the run time environment for floating point operations
must be initialized at program startup and used at link time.
The following table describes the flags that are supported.
To |
Use the flag |
Enable trap on invalid floating-point operations.
|
V
|
Disable trap on invalid floating-point operations.
|
v
|
Enable trap on divide by zero.
|
Z
|
Disable trap on divide by zero.
|
z
|
Enable trap on floating-point overflow.
|
O
|
Disable trap on floating-point overflow.
|
o
|
Enable trap on floating-point underflow.
|
U
|
Disable trap on floating-point underflow.
|
u
|
Enable trap on floating-point operations that produce inexact results.
|
I
|
Disable trap on floating-point operations that produce inexact results.
|
i
|
Enable sudden underflow (flush to zero) of denormalized values.
|
D
|
Disable sudden underflow (flush to zero) of denormalized values.
|
d
|
All trapping behaviors are disabled by default.
In addition to the flags, you can specify values for the
rounding mode. The following values are available:
- RN Round to nearest. This is the default value.
- RU Round upward toward +infinity.
- RD Round downward toward -infinity
- RZ Round toward zero, that is, truncate.
For more information on the +FP option, see the HP-UX Floating Point Guide
available at: http://www.docs.hp.com
|