rld(1)
rld - runtime linker rld.debug - runtime linker with debugging support
As shipped in IRIX 6.5.7. Unchanged since IRIX 6.5.
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 _RLD_LIST 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 _RLD64_LIST, and the one for new 32-bit ABI programs is _RLDN32_LIST. 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 _RLD_ROOT or LD_LIBRARY_PATH. 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 _RLD64_ROOT or LD_LIBRARY64_PATH. 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 _RLDN32_ROOT or LD_LIBRARYN32_PATH. 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 LD_LIBRARY_PATH if defined in the environment at the time of execution; 4. The default library search path. DT_RPATH is a colon(:) separated list of directories. DT_RPATH in the library search algorithm outlined above refers to the net list of paths at the time the search is done. DT_RPATH is actually a tag in the .dynamic section of a DSO or executable whose value is a string. DT_RPATH is set in any given DSO or the executable via the -rpath switch to ld(1) when the executable or DSO is created. Each DT_RPATH 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. LD_LIBRARY_PATH 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. LD_LIBRARY64_PATH and LD_LIBRARYN32_PATH are treated in a similar fashion. _RLD_ROOT is a colon(:) separated list of directories; and, if defined, is appended to the front of DT_RPATH and the default path. _RLD64_ROOT and _RLDN32_ROOT 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 _RLD_PATH to the full path of another runtime linker. rld.debug is a version of rld that has debugging support. By setting the environment variable _RLD_PATH 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 _RLD64_PATH and the debugging version of rld is /usr/lib64/rld.debug. For new 32-bit ABI programs, the environment variable is _RLDN32_PATH and the debugging version of rld is /usr/lib32/rld.debug. rld also supports the environment variable LD_BIND_NOW as documented in the SYSTEM V ABI pg 5-14. If LD_BIND_NOW is set to "1" or "on", then the dynamic linker processes all relocation before transferring control to the program, if LD_BIND_NOW 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. 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 _RLD_ARGS 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. -ignore_all_versions ignore versions on all objects. -ignore_versionshared_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). -ignore_unresolved 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). -quickstart_info 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 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 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) 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. 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 _RLD_LIST 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. _RLDN32_LIST and _RLD64_LIST don't suffer from this as they are only interpreted in a single ABI each. See the description of _RLD_LIST earlier in this man page. Adding setenv _RLDN32_LIST DEFAULT setenv _RLD64_LIST DEFAULT 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.