Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ rld(1) — IRIX 6.5.3f

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

ld(1)

cc(1)

dlopen(3)

dlclose(3)

dlsym(3)

dlerror(3)

sgidladd(3)

sgidlopen_version(3)

sgigetdsoversion(3)

dso(5)

gp_overflow(5)



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



Typewritten Software • bear@typewritten.org • Edmonds, WA 98026