RLD(1) RLD(1)
NAME
rld - runtime linker
rld.debug - runtime linker with debugging support
DESCRIPTION
rld, the runtime linker, exists in appropriate versions for executables
in each ABI (Application Binary Interface) available. rld is invoked
when running a dynamic executable. rld maps in shared objects used by
this executable, resolves relocations as ld does at static link time, and
allocates common if required.
When any dynamic executable is run, the system will first run an
interpreter which is responsible for collecting together the appropriate
objects, mapping them into memory and resolving references during
runtime. The name of the interpreter is included in the executable file.
Dynamic execution is only supported with ELF format executables. Such
executables will have an INTERP section which specifies the name of this
interpreter. The default name of this interpreter is /usr/lib/libc.so.1.
Any binary which hopes to conform to the MIPS SVR4 ABI should use the
name /usr/lib/libc.so.1 as its interpreter.
For 64-bit (64-bit ABI) programs the name of this interpreter is
/usr/lib64/libc.so.1. The discussion below applies to 64-bit programs if
the directory /usr/lib64 is substituted for the directory /usr/lib and
the directory /lib64 is substituted for /lib.
For new 32-bit ABI programs the name of this interpreter is
/usr/lib32/libc.so.1. The discussion below applies to new 32-bit ABI
programs if the directory /usr/lib32 is substituted for the directory
/usr/lib and the directory /lib32 is substituted for /lib.
The file /usr/lib/libc.so.1 is the standard C/system library in the form
of a shared object. In addition /usr/lib/libc.so.1 contains code which
will load the interpreter into its address space and set it to work. The
default such interpreter is /lib/rld.
One of the primary features of dynamic linking is that it gives users the
ability to change library implementations without recompiling the
executable. Some mechanisms for this are listed below. However,
/usr/lib/libc.so.1 is not subject to any of the mechanisms listed below,
since it is known to the executable as the interpreter as well as a
needed shared object. If you wish to substitute /usr/lib/libc.so.1, the
best way is to make use of the -I flag to the linker (ld(1)). This can
be passed from the compiler driver using the -Wl,-I,myinterpname format.
However, any such shared object specified must be able to act as
interpreter (or invoke rld).
rld constructs an explicit shared object list based on the information
listed in the .liblist section. For 32-bit programs, if the environment
variable RLDLIST is set, it overrides the dynamic executable's original
list (after the original list is constructed). The corresponding
environment variable for 64-bit programs is RLD64LIST, and the one for
Page 1
RLD(1) RLD(1)
new 32-bit ABI programs is RLDN32LIST.
For n32 (new 32-bit ABI) or 64-bit (64-bit ABI) programs, if _RLDN32_LIST
or _RLD64_LIST is not specified, then rld will honor _RLD_LIST if
specified.
The user may include DEFAULT in _RLD_LIST (_RLDN32_LIST/_RLD64_LIST) to
include the executable's original objlist and have rld to add new shared
objects just before and/or after it. The object list is specified as a
colon (:) separated list of shared objects. The liblists of shared
objects newly added from _RLD_LIST, _RLDN32_LIST, or _RLD64_LIST are
intentionally not processed: so it is up to the user to make the list
complete.
Because there are three distinct ABI's used by Irix programs with
accompanying libraries, there are three distinct sets of RLD search paths
and three sets of environment variables.
The default library search path for o32 (32-bit ABI) programs is
(/usr/lib:/usr/lib/internal:/lib), which can be overridden by either of
the environment variables RLDROOT or LDLIBRARYPATH.
The default library search path for 64 (64-bit ABI) programs is
(/usr/lib64:/usr/lib64/internal:/lib64), which can be overridden by
either of the environment variables RLD64ROOT or LDLIBRARY64PATH.
The default library search path for n32 (new 32-bit ABI) programs is
(/usr/lib32:/usr/lib32/internal:/lib32), which can be overridden by
either of the environment variables RLDN32ROOT or LDLIBRARYN32PATH.
For n32 or 64-bit programs, if LD_LIBRARYN32_PATH or LD_LIBRARY64_PATH is
not specified, then rld will honor LD_LIBRARY_PATH if specified. As a
result, if LD_LIBRARY_PATH is set for an o32 program it is a very good
idea to also set LD_LIBRARYN32_PATH and LD_LIBRARY64_PATH to something
("" will suffice) to avoid having LD_LIBRARY_PATH apply accidentally to
n32 and 64 applications in that environment.
The search path for shared objects is acquired in the following order:
1. The path of the shared object if given in the liblist,
(i.e., if the soname of the shared object has a path (see ld(1));
2. DT_RPATH if DT_RPATH is defined in the executable or
any DSO that rld has opened.
3. Use LDLIBRARYPATH if defined in the environment at
the time of execution;
4. The default library search path.
Page 2
RLD(1) RLD(1)
DTRPATH is a colon(:) separated list of directories. DTRPATH in the
library search algorithm outlined above refers to the net list of paths
at the time the search is done. DTRPATH is actually a tag in the
.dynamic section of a DSO or executable whose value is a string.
DTRPATH is set in any given DSO or the executable via the -rpath switch
to ld(1) when the executable or DSO is created. Each DTRPATH appends to
the list of directories at the time the executable or DSO is loaded.
There is no mechanism to remove anything from the list of directories
which rld builds for the executable.
LDLIBRARYPATH is a colon(:) separated list of directories; and, if
defined, specifies an extra set of directories in which rld is to look
when searching for shared objects.
LDLIBRARY64PATH and LDLIBRARYN32PATH are treated in a similar
fashion.
RLDROOT is a colon(:) separated list of directories; and, if defined,
is appended to the front of DT_RPATH and the default path.
RLD64ROOT and RLDN32ROOT are treated in a similar fashion.
To ensure compatibility, applications may choose to disallow exec-time or
runtime library replacement. ld supports the -no_library_replacement,
flag to facilitate this feature.
Security dictates that rld should not allow library replacement for
setuid and setgid programs unless the user is root.
Users can replace the default rld binary by setting the environment
variable RLDPATH to the full path of another runtime linker. rld.debug
is a version of rld that has debugging support. By setting the
environment variable RLDPATH to /usr/lib/rld.debug, it replaces the
default rld as the runtime linker, and the debugging features it supports
are available.
For 64-bit programs, the environment variable is RLD64PATH and the
debugging version of rld is /usr/lib64/rld.debug.
For new 32-bit ABI programs, the environment variable is RLDN32PATH and
the debugging version of rld is /usr/lib32/rld.debug.
rld also supports the environment variable LDBINDNOW as documented in
the SYSTEM V ABI pg 5-14. If LDBINDNOW is set to "1" or "on", then the
dynamic linker processes all relocation before transferring control to
the program, if LDBINDNOW is set to "0" or "off", or does not occur in
the environment, then the dynamic linker is permitted to perform symbol
resolution and relocation for functions lazily, ie avoid them until the
functions are called.
Page 3
RLD(1) RLD(1)
Runtime linking interface
The system calls dlopen(3), dlsym(3), dlclose(3), dlerr(3)
sgidlopen_version(3) and sgidladd(3) are provided to supply users with
on-demand loading of objects. These routines are found in
/usr/lib/libc.so.1; no special flags are needed at link time to access
them.
rld options
Users may specify runtime linker options by setting the RLDARGS
environment variable to any combination of the following options. rld
options are not needed to run properly coded and linked executables: they
are provided for special situations and debugging.
-clearstack
For programs that assume local variables to be initialized to zero
upon function entry, this option forces rld to zero any stack it
uses before before calling the program's main program. Properly
written programs never assume that the stack is zeroed (therefore
properly written programs do not expect local variables to be
automatically initialized except as provided for in the
programming-language definition). If a program or any of its DSOs
(as seen at startup of the program) dynamic section flags do not
have RHF_SGI_ONLY set then -clearstack is automatically turned on.
-ignoreallversions
ignore versions on all objects.
-ignoreversionshared_object
ignore the version stamp checking on the object specified. This
option can be specified multiple times (in case multiple shared
objects should have their versions ignored).
-ignoreunresolved
doesn't complain or abort when rld can't resolve unresolved data
symbols.
-log file
prints all messages to file instead of the default action of
printing all messages to the device /dev/tty (if /dev/tty is
unavailable, the system log (/var/adm/SYSLOG) is used instead).
rld.debug options
The following additional options are available when the appropriate
_RLD_PATH environment variable is set appropriately to /usr/lib/rld.debug
(for n32, _RLDN32_PATH to /usr/lib32/rld.debug. for 64, _RLD64_PATH to
/usr/lib64/rld.debug).
Page 4
RLD(1) RLD(1)
-quickstartinfo
Tells user whether quickstart has failed.
-interact
rld interactively prompts the user on stdin to fix problems in the
link (e.g. rld will ask the user to provide a full pathname for a
missing shared object.)
-trace
generally shows the flow of code in rld itself and prints individual
symbol actions.
-v generally prints rld actions at the level of the DSO, not at the
symbol level. -v is less verbose than -trace.
-debug symbol
prints a verbose description of the actions taken resolving all
symbols(the option is those two literal words: there is no provision
for tracing the actions on only selected symbols). This produces
lots of output so it is normally most useful to also use -log file
to direct the rld output to file.
Runtime linker entry points
rld is entered when a program using dso is started via exec() and through
lazy text resolution during program execution. Before exiting, programs
or objects need to call _rld_new_interface(_SHUT_DOWN) to ensure that the
program executes all of the code specified by -fini flag to ld(1). The
_exit(2) library routine calls _rld_new_interface(_SHUT_DOWN). Any call
to _rld_new_interface(_SHUT_DOWN) runs the -fini code on all objects so
it cannot safely be done just anywhere! As is mentioned below in this
document, _rld_new_interface(_SHUT_DOWN) is not a call any application
should make: it is for the system developers only.
System developer's interface
rld keeps a doubly linked list of structures and crt1.o contains a
pointer to the head of the list of obj structures called __rld_obj_head .
In an o32 executable, this points to a linked list of objList structures
(/usr/include/obj_list.h). each of which has a 'data' element which is a
pointer to a 'struct obj' (/usr/include/obj.h) (even though the field is
not declared as a pointer). In an n32 executable, __rld_obj_head points
to a linked list of Elf32_Obj_Info structures (/usr/include/objlist.h).
In a 64-bit executable, __rld_obj_head points to a linked list of
Elf64_Obj_Info structures (/usr/include/objlist.h). The 'oi_magic'
element of each Elf32_Obj_Info or Elf64_Obj_Info is all-bits-on
(0xffffffff) to make it easier to determine which list type is in use a
32-bit executable.
User entry points
Page 5
RLD(1) RLD(1)
The interface described below is for system development only. It is not
recommended nor supported for use in end-user code. It is described here
for the benefit of system developers.
#include <rld_interface.h>
void *_rld_new_interface(Elf32_Word operation, ...)
Here is a list of currently defined operations:
(int)_rld_new_interface(_SHUT_DOWN)
This function calls the routine specified by the -fini flag to ld(1)
on all open DSOs (and the main program) in the reverse of the order
that the -init sections were run.
(char *)_rld_new_interface(_RLD_FIRST_PATHNAME)
This function returns the string "MAIN" and resets an internal
pointer inside of rld to set up for calls to This interface is not
thread-safe: multiple threads doing this will get erroneous results.
Any call to _rld_new_interface(_RLD_MODIFY_LIST,...) after calling
_rld_new_interface(_RLD_FIRST_PATHNAME) and before calling
_rld_new_interface(_RLD_NEXT_PATHNAME) will interfere with the
correctness of the _rld_new_interface(_RLD_NEXT_PATHNAME) returns.
_rld_new_interface(_RLD_NEXT_PATHNAME). Any operation (including
delay-loading a DSO as a result of lazy-function-evaluation) that
causes the DSO list to be altered may interfere with the correctness
of the _rld_new_interface(_RLD_NEXT_PATHNAME) returns.
(char *)_rld_new_interface(_RLD_NEXT_PATHNAME)
This function returns the next pathname in rld's object list and
increments its internal pointer. It returns NULL when rld reaches
the end of the list. This interface is not thread-safe: multiple
threads doing this will get erroneous results. Calls to
_rld_new_interface(_RLD_NEXT_PATHNAME) cannot be interspersed with
calls to _rld_new_interface(_RLD_MODIFY_LIST,... as doing so will
interfere with the correctness of the
_rld_new_interface(_RLD_NEXT_PATHNAME) returns. Any operation
(including delay-loading a DSO as a result of lazy-function-
evaluation) that causes the DSO list to be altered may interfere
with the correctness of the _rld_new_interface(_RLD_NEXT_PATHNAME)
returns.
(char *)_rld_new_interface(_RLD_MODIFY_LIST, Elf32_Word operation, char
*original_pathname, char *name)
This function allows users to link and unlink objects. When users
insert or add an object, they must specify the new object in name.
They may specify a full path or take advantage of rld's searching
mechanism. Users are not allowed to insert before MAIN. If
orig_pathname is zero, rld will operate on the last element in the
Page 6
RLD(1) RLD(1)
list. The exact function performed depends on the parameter
operation, which can take the following values:
_RLD_OP_NONE does nothing.
_RLD_OP_INSERT adds a new object specified by name before the
object specified by orig_pathname. Objects cannot be added
before main().
_RLD_OP_ADD adds a new object specified by name after the
object specified by orig_pathname. If orig_pathname is omitted,
the new object will be added at the end of the object list.
_RLD_OP_DELETE deletes orig_pathname from the object list.
_RLD_OP_REPLACE replaces orig_pathname with the object
specified by name in the object list.
(char *)_rld_new_interface(_RLD_ADDR_TO_NAME, Elf32_Addr address)
This function returns the symbol name of the address passed in as
argument, NULL if no symbol corresponds to that address in the
current process. In a 64-bit application, the second argument is of
type Elf64_Addr.
(Elf32_Addr)_rld_new_interface(_RLD_NAME_TO_ADDR, char *name)
This function returns actual address of name. It returns NULL if rld
cannot find the passed argument. In a 64-bit application, the value
returned is of type Elf64_addr).
(char *)_rld_new_interface(_RLD_VERSION_EXPECTED, char *soname)
This function returns the version string in MAIN's liblist entry for
soname.
(Elf32_Addr)_rld_new_interface(_RLD_SPROC_NOTIFY)
This function signals to rld that sproc has been called and that rld
has to worry about multiple sproc threads. The call is made by
libc.so.
(Elf32_Addr)_rld_new_interface(_RLD_SHUTDOWN_THREAD)
This function was intended to signal to rld that a thread is trying
to exit. Currently does nothing.
(Elf32_Addr)_rld_new_interface(_RLD_SPROC_FINI)
Page 7
RLD(1) RLD(1)
This function signals to rld that multiple sproc(2) threads support
can be turned off. It is called on behalf of, and in, the child
process after a fork(2) by the fork code in libc.so.
EXAMPLES
Here are some csh aliases for control of rld tracing that you may find
useful. Notice that there are three sets of tracing aliases, one for
each ABI (o32, n32, 64). See file(1) for how to identify the ABI of a
particular executable.
# trace o32 rld issues
alias ra \
'setenv _RLD_PATH /usr/lib/rld.debug ;'\
'setenv _RLD_ARGS "\!*" ;'
alias nora \
'unsetenv _RLD_ARGS ;'\
'setenv _RLD_PATH /lib/rld ;'
# trace n32 rld issues
alias ra32 \
'setenv _RLDN32_PATH /usr/lib32/rld.debug ;'\
'setenv _RLD_ARGS "\!*" ;'
alias nora32 \
'unsetenv _RLD_ARGS ;'\
'setenv _RLDN32_PATH /lib32/rld ;'
# trace 64 rld issues
alias ra64 \
'setenv _RLD64_PATH /usr/lib64/rld.debug ;'\
'setenv _RLD_ARGS "\!*" ;'
alias nora64 \
'unsetenv _RLD_ARGS ;'\
'setenv _RLD64_PATH /lib64/rld ;'
Watch RLD when running an o32 binary: 'ls'
% ra -trace <-- turns on tracing of o32 rld
% ls
27312:[rld] Entering RLD through MAIN
27312:ls: [rld] mapped ls at 0x400000
27312:ls: [rld] mapped /lib/libc.so.1 at 0xfa00000
27312:ls: [rld] found _end in ls for libc.so.1 at 0x10007000
27312:ls: [rld] number of objs in the objlist is 2
27312:ls: [rld] Exiting RLD through MAIN
RCS libX11.so.2 libc.so libl.a setup
acrt1.o libXaw.a libc.so.1 libm.a sgicc.cfg
crt1.o libXext.a libc.so.O libmld.a sgild.cfg
% nora <-- turns off all o32 rld debugging options.
Page 8
RLD(1) RLD(1)
Watch RLD when running an n32 binary: 'ci'
% ra32 -v <-- turns on verbose mode in n32 rld
% ci -l c.c
14891:_RLD_ARGS = "-v"
14891:_RLD_ROOT = /
14891:LD_LIBRARYN32_PATH = none
14891:ci: mapped ci at 0x10000000
14891:ci: mapped /usr/lib32/libc.so.1 at 0xfa00000
RCS/c.c,v <-- c.c
file is unchanged; reverting to previous revision 1.1
done
% nora32 <-- turns off all n32 rld debugging options.
ERROR REPORTING
Most error messages are written to /dev/tty, unless otherwise noted
above. If rld should encounter an error condition for a process which
does not have a valid /dev/tty attached, it will write the messages to
/var/adm/SYSLOG instead. (The system log is written via calls to
syslog(2).)
CHANGING ROOT
A copy of the device /dev/zero is essential to the operation of rld.
Thus in most uses of chroot(1), it will be necessary to put a copy of
/dev/zero in the newly-created root.
SEE ALSO
ld(1), cc(1), dlopen(3), dlclose(3), dlsym(3), dlerror(3), sgidladd(3),
sgidlopen_version(3), sgigetdsoversion(3), dso(5), gp_overflow(5)
Also see "System V Application Binary Interface" and "System V
Application Binary Interface: MIPS Processor Supplement" and "MIPSpro N32
ABI Handbook"
NOTES
Listing a particular DSO in RLDLIST is likely to lead to problems and
failures unless all three environment variables are set. A typical
result is a message like "... rld: Fatal Error: Cannot Successfully map
soname ...". For example, consider a test app "a.out" which is o32 and a
specific o32 DSO, /tmp/mydso.so:
unsetenv _RLDN32_LIST _RLD64_LIST
setenv _RLD_LIST "/tmp/mydso.so:DEFAULT"
This will likely fail because some command (or the app itself) will
attempt to fork/exec some n32 application and /tmp/mydso.so is o32, not
n32. RLDN32LIST and RLD64LIST don't suffer from this as they are
only interpreted in a single ABI each. See the description of RLDLIST
earlier in this man page. Adding
setenv _RLDN32_LIST DEFAULT
setenv _RLD64_LIST DEFAULT
Page 9
RLD(1) RLD(1)
will fix the problem in this example.
DIAGNOSTICS
Here we explain a message from rld whose meaning is not apparent.
The aggregate IEEE exceptions required (OEX_FPU_MIN) (0xnn) not as
complete as the aggregate IEEE exceptions permitted
(OEX_FPU_MAX>>8)(0xnn).
As the executable and each DSO is accessed (before the app begins
running) the .MIPS.options section (visible with elfdump -op) is used
to compute an aggregate set of floating point exceptions to enable.
For example, use of the -trapuv flag to the compiler results in a
request for invalid exception trapping be enabled. Whereas use of
certain high optimizations for -mips4 and -mips3 require that those
exceptions be turned off so that speculative loads of floating-point
values can be executed silently. See compiler options
-TARG:exc_max=[I][U][O][Z][V], -TARG:exc_min=[I][U][O][Z][V], and
-TENV:X=0..5.
Delay-loaded DSOs and dlopen()'d and sgidladd()ed DSOs are not
factored in till the actual sgidladd/dlopen is called. The
OEX_FPU_MIN field of each object is OR'd with the others. The non-
zero bits represent the set of floating point exceptions that the app
wants to catch (more precisely exceptions that some part of the app
or a DSO want to catch). The OR'd-together OEX_FPU_MIN fields are
used to determine what set_fpc_csr() fields to set to 1 ( rld never
sets any set_fpc_csr() fields to zero). The OEX_FPU_MAX field of
each object is AND'd with the others. The zero-bits represent
floating-point exceptions that must not be caught (for example, if
the code generator is issuing speculative loads, the invalid-value
exception should not be caught). If some bits are OFF in OEX_FPU_MAX
that are ON in OEX_FPU_MIN that represents an impossible scenario:
exceptions must be caught and simultaneously must not be. For
example, this could happen if object is compiled requesting trapping
uninitialized variables and requesting requesting a high optimization
resulting in the code generator issuing speculative loads.
As each DSO is dlopen()ed or delay-loaded or sgidladd()ed or
dlclose()ed these flags are recalculated. If user or library code
has changed the 5 exception-flag-enable fields from a previous
setting by rld then rld updating of the exception-enable fields
silently ceases for this execution.
rld never turns off exception-enable flags once it has turned them
on.
Use elfdump -op <objectname> to see the OEX fields of an executable
or DSO.
Page 10