SGI Techpubs Library

IRIX 6.5  »  Man Pages
find in page



     DSO - Dynamic Shared Object (DSO)


     This man page describes Dynamic Shared Objects (DSOs).

     It is divided into the following 4 sections:

     * Overview

     * Linking and building DSOs

     * Performance considerations

     * Frequently asked questions


     A DSO is an ELF format object file.  It is very similar in structure
     to an executable program, but it has no main program.  It has the
     following components:

     * A shared component, which consists of shared text and read-only

     * A private component, which consists of data and the Global Offset
       Table (GOT).

     * Several sections that hold information needed to load and link the

     * A liblist, which is the list of other DSOs referenced by this
       object.  Most libraries supported on IRIX platforms are available as

   Position Independent Code (PIC)
     A DSO is relocatable at runtime; it can be loaded at any virtual
     address.  A consequence of this is that all references to external
     symbols must be resolved at runtime.

     References from a private region (that is, from private data) are
     resolved at load time.  References from a shared region (that is, from
     shared text) go through the indirection table, which is also called
     the Global Offset Table (GOT), and incur a small performance penalty.

     The GOT helps facilitate Position Independent Code (PIC).  PIC is code
     that satisfies references indirectly by using the GOT, which allows
     code to be relocated simply by updating the GOT.  Each executable and
     each DSO has its own GOT.  The GOT is a data table with the actual
     addresses of global data with appropriate code generation and linking
     support.  The linker, ld(1), constructs the GOT.

     PIC satisfies references indirectly by using the GOT, which allows
     code to be relocated simply by updating the GOT.  PIC can be shared by
     multiple users.  Each program must have its own data space.  Code
     sharing and independent data is arranged automatically by the
     compilation and run-time systems.

     Code compiled for use in a DSO is PIC.  Non-PIC code is usually
     referred to as non-shared.  Non-shared code and PIC cannot be mixed in
     the same object.

   What Happens at Runtime?
     The runtime events are as follows:

     1. exec(2) loads the main program and then loads one of the following
        interpreters as specified in the main program:

        * /usr/lib/ is loaded for programs compiled with the -32
          compiler option.

        * /usr/lib32/ is loaded for programs compiled with the
          -n32 compiler option.

        * /usr/lib64/ is loaded for programs compiled with the -64
          compiler option.

     2. The interpreter loads rld(5), the runtime linking loader, which
        finishes the exec(2) operation.  Starting with the main program's
        liblist, rld(5) loads each DSO on the list that is not marked to be
        delay-loaded.  rld(5) reads that object's liblist and repeats the
        operation until all DSOs have been loaded, in a breadth-first
        manner.  The breadth first loading process, which ignores objects
        marked to be delay-loaded, results in defining a sequence of

     3. rld(5) allocates storage for COMMON block symbols and fixes up
        symbolic references in each loaded object.  This is necessary
        because the location at which the object will be loaded is not
        known until runtime.  To look up a given symbol in the process of
        fixing up symbolic references, rld(5) examines each object's
        dynamic symbol table.  If rld(5) finds a strong symbol that
        satisfies the reference (that is, it has the name of the given
        symbol and is an external definition) it stops with that symbol.
        If it does not find a strong definition with that name, then the
        first weak symbol found is accepted as the definition.

     4. Each object's -init code is executed.  These routines are specified
        with the linker's init option (ld -init).  For information about
        -init code, see ld(1).

     5. Control transfers to __start in the main program.

     The sequence at which the -init code is run is important to
     applications and DSOs that have -init code.  By default, objects are
     taken in reverse order of the sequence defined in loading.  If -init
     code in one DSO calls a DSO with -init code that has not yet run, then
     the -init code in the called DSO is run before the called DSO routine
     is actually called.  Thus, the default order is not followed.

     It is not an error for DSOs to mutually call one another, even
     indirectly, from within -init sections, but the resulting DSO ordering
     can be confusing and can vary depending on actions in the application
     -init code.  The -init code in delay-loaded DSOs is not run until the
     DSO is actually loaded, and the delay-loaded DSO is loaded when some
     routine in the delay-loaded DSO is called.

     Do not include calls to sproc(2), nsproc(2), sprocsp(2), or any POSIX
     threads (pthreads) routines from within -init or -fini code.  The
     following table describes the problem with -init and -fini code in
     pthreads and sproc(2) applications:

                         sigprocmask(2) Getting   sigprocmask(2) Setting
     Threads?            Mask Bits                Mask Bits
     sproc(2) threads    Sees more masked than    Settings lost on exit
                         non-init.                of -init and -fini.
     pthreads            Sees more masked than    Application settings
                         non-init.                preserved.
     No threads          Sees true setting.       Application settings

     The preceding table entries can be explained as follows:

     * In the Threads? column, An sproc(2) threads application is one that
       is using sproc(2), nsproc(2), or sprocsp(2).  A pthreads application
       is one that has linked in.  A No threads application
       is any other application.

     * Sees more masked than non-init means that -init and -fini code do
       not get the true mask bits.  Instead, nearly all signals are marked
       as masked.

     * Settings lost on exit of -init and -fini means that on exit of the
       nested set of -init or -fini functions, the set of mask bits set on
       entry to the functions is restored.  Any setting done by the -init
       or -fini code is lost.

     * Application settings preserved means that the sigprocmask(2) bit
       settings that are made by the -init or -fini code are preserved on
       exit of the -init or -fini function set.

     * Sees true setting means that the mask bits that sigprocmask(2)
       returns to -init and -fini code are the true application mask bits.

     As the preceding table shows, the complexities with signal masks
     inhibit successful sigprocmask(2) operation in -init or -fini code.
     Generally, the results are not going to be what is desired.

     Also ignored, in theory, are symbols in any DSO that is loaded at
     runtime because it is on the liblist of a DSO opened by dlopen(3C) or
     sgidlopen_version(3C).  rld(5) makes the liblist DSO symbols visible,
     but no application should count on this visibility.  However, if a
     DSO's symbols are visible for any reason (for example, because it was
     in the main program's liblist), that DSO is not hidden just because it
     is also on the library list of a DSO opened with dlopen(3C) or

     When execution terminates, the -fini code of each DSO and the base
     a.out file is run in the opposite order the actual -init code was run
     (or would have been run, in the case of DSOs with -fini code but no
     -init code).  -fini code and -init code consist of code specified as
     an argument to the ld(1) For more information on -fini code and -init
     code, see the rest of this man page and see ld(1).

     Other factors can affect the general load process, too.  For more
     information, see the information on Quickstart and delayed loads on
     this man page and see the sgidladd(3C), sgidlopen_version(3C), and
     dlopen(3C) man pages.

   -init Code Runtime Ordering
     The general order in which the base executable DSO's -init code is run
     is specified by the MIPS Application Binary Interface (API).  For more
     information on this ABI, see the URLs mentioned in the SEE ALSO

     Before an -init in object A is run, you can assume that all -init
     sections in DSOs that A depends on have been run.  However, if -init
     code calls a DSO with -init code that has not yet run, the -init code
     of the called DSO is run first.

     The physical ordering starts with the last DSO in rld(5)'s list and
     works toward the executable file.  This is a depth-first postorder
     call of -init code.  This is a particular choice of ordering within
     the conceptual framework.  The physical ordering is not specified by
     the MIPS ABI.

     The run order of delay-loaded DSOs and DSOs that have been opened by
     dlopen(3C) is recorded so that -fini operations occur in reverse

     Any DSO that is delay-loaded during the execution of -init code
     changes the order in which -init sections are run.  The actual manner
     of the changes is difficult to predict.  At the time of the
     delay-load, the -init code scan is restarted anew (new due to the new
     DSO) at the end of rld(5)'s list.

   -fini Code Runtime Ordering
     The -fini code of the DSOs in the base executable is run choosing DSOs
     in the opposite order the actual -init code was run (or would have
     been run, in the case of DSOs with -fini code but no -init code).

   Limitations on -init and -fini Code
     In most versions of rld(5), -init and -fini code could not
     successfully perform delay-load operations, such as dlopen(3C),
     sgidladd(3C), dlsym(3C), dlclose(3C), or implicit delay-load
     operations, if the application used sproc(2), sprocsp(2), or pthreads
     (nsproc is no longer a public function).  Threaded applications hung
     if such operations were included in -init or -fini code or were nested
     codes outside of -init or -fini code.

     The current release of rld(5), however, supports nested delay-load
     operations, but it is unwise to depend too much on this support.  For
     example, it is unwise to use delay-loading with C++ global
     initialization code because much about the interaction of name
     resolution (name binding and symbol binding) with nested delay-load
     operations is unspecified.

     For example, calling a delay-load routine or calling delay-loaded
     functions in different orders depending on startup conditions means
     that the ordering of DSOs on rld(5)'s list of DSOs may vary.  If the
     order varies and there are multiple definitions of an external
     (different functions with the same name), exactly what is executed
     from run to run may differ.  Considering that is it difficult, in C++,
     to control the sequence in which different compilation units -init
     code is executed, and potentially, you have serious application

     It is also difficult to debug such code as debuggers often have
     difficulting intercepting calls in -init sections.

     In multithreaded programs, -init and -fini code should avoid attempts
     to acquire (by using pthread_mutex_lock(3P), for example) resources
     owned by other threads, unless it can be guaranteed that the other
     thread can release the resource without performing a delay-load
     operation or lazy text resolution.  Should the thread owning the
     resource make a call into rld(5), the threads deadlock.

     It is difficult to predict whether execution of a given section of
     code requires lazy text resolution.  A DSO's GOT can be reset to point
     at function stubs when it fails to Quickstart or after delay-load
     operations that might affect resolution of its symbols.  See the
     section on Quickstart in the PERFORMANCE CONSIDERATIONS section of
     this man page for more information on function resolution.

     The C++ runtime system uses the -init and -fini mechanism to construct
     and destroy static objects.  Therefore, constructors and destructors
     for such objects should avoid blocking calls if DSOs using them are to
     be manipulated by dlopen(3C) or dlclose(3C) or are to be delay-loaded
     within a multithreaded program.


     Assume that your library is in an archive libfoo.a of object files,
     all of which have been compiled with the ld(1) command's -shared
     option.  The library references symbols found in,,, and, but most programs never use the path that
     requires  It is recommended that you build your DSO,, in the following way:

          -all libfoo.a
          -delay_load -lnetls

     This builds a DSO called that directs rld(5) to load,, and whenever is loaded.  This
     command line also loads if it is ever referenced.

     NOTE:  If you have any C++ object files among the objects making up
     your DSO, you must replace ld in the previous example command with CC.
     That is, your command line should be as follows:

          CC -elf -shared ... -o -all libfoo.a ...

     However, you do not have to do anything special at all to use such C++
     DSOs when linking other programs against these DSOs.  You can link C++
     DSOs into C, C++, or Fortran programs using your usual link commands
     or link other DSOs against these C++ DSOs without taking any special
     action.  For example, the following command line links the preceding
     C++ DSO properly:

          f77 fortran_prog.o -lfoo

   Controlling Symbols Exported by a DSO
     One benefit from using DSOs is the ability to release new versions of
     an object and be assured that objects linked against the old version
     will work with the new version.  This is impossible to guarantee,
     however, if the set of symbols exported by an object cannot easily be
     understood by the object's creator.  ld(1) provides several options to
     help you control the symbols that are exported by a DSO.

     By default, ld(1) does not export symbols that are supplied by a
     linked-in archive or DSO.  The developer is probably only a consumer
     of the linked-in object, not  an exporter.  In a subsequent release,
     the developer may not require the linked-in object, and if the symbols
     provided by the linked-in object had been exported by the developer's
     object, the new object would no longer be upwardly compatible with the
     original version.  This behavior can be overridden by using the
     -exports option on the ld(1) command.  This default symbol hiding
     behavior, with respect to archives, is also overridden when building a
     DSO from an archive using the -all option.

     You can control the list of symbols that are exported by using the
     following ld(1) options:  -exported_symbol, -exports_file, -exports,
     -hides, -hidden_symbol, and -hides_file.  The first two options let
     you specifically list the symbols to be exported by the DSO.  The
     exported_symbol option is followed by a comma-sepatated list of names.
     The exports_file option accepts a file name that contains a
     space-separated (including newlines) list of names.  If any symbols
     are specifically exported, only those symbols are exported.  All other
     symbols are automatically hidden.  The last two options specify a list
     of symbols that are not to be exported by the DSO.  For more
     information on the ld(1) options, see the ld(1) man page.

     There are two consequences of hiding symbols.  First, those symbols do
     not provide resolution to any undefined symbols in an object that
     links in the DSO.  Second, any references to those symbols within the
     DSO are resolved internally to the hidden symbol.

   Rules of Thumb
     The following list contains things to remember when using the ld(1)

     * Use the -no_unresolved option to find unresolved symbols.  It is not
       always possible to supply all the DSOs that will be referenced by on the link line, but in general, libraries should be
       self-contained.  This is especially true for subsequent releases of
       a DSO.  If a DSO has any unresolved references, they must be
       resolved by some other loaded object.  Having unresolved symbols
       invites disaster because there is no guarantee that the symbols will
       be resolved.  Thus, the application may not run.

     * Link against the minimum set of .so files needed.  Loading a DSO
       carries a cost.  Linking against unneeded DSOs causes them to be
       loaded even if they are never referenced.  ld(1) issues a message
       when you have linked against a DSO that resolves no symbols.

     * When building a C++ DSO, specify the -exports option for any DSO
       that provides the definitions of classes from which classes in the
       object being created are derived.

       Specifying -exports in this case ensures that consumers of the
       object being created can create subclasses of classes provided by
       that object without having to know the complete set of DSOs that
       need to be loaded.

       Using the -exports option in this case may bring in unwanted
       symbols.  Use the -exported_symbol, -exports_file, -hidden_symbol,
       or -hides_file options where appropriate.

     * Use the -rdata_shared option to move all read-only data into the
       shared segment.  Unfortunately, many programs write to supposedly
       read-only data.  The -rdata_shared option is disabled by default for
       this reason.  The -use_readonly_const compiler option is enabled by

     * Always use thesoname option to provide a specific soname for the
       DSO.  If you don't, the name is taken (with path if present on the
       link line) from the o option and in many cases this is not what you

       The following example ends up with an soname of tmp and the runtime
       linker will not be able to find

                    cc -shared t.o -o tmp
                    mv tmp

       Use elfdump -L foo/ |grep SONAME to see the soname of

            cc -shared t.o  -soname -o tmp
            mv tmp

       This is the way the above can be made to work properly.  It is
       crucial that the soname and the final path element of the file (and
       and any symlinks pointing to the DSO) agree precisely (though if
       there are trailing SGI version numbers in the file name, such are
       not required or desired in the soname).

       Example: has soname of and no version string.
       This is the norm for most DSOs you will build (in most cases you are
       not worrying about DSO compatibility: you will simply rebuild
       everything when things change).

       Example: has soname of and version of sgi1.0.
       This is a standard approach on IRIX as used for libc and other
       system DSOs.  See the versioning info in the FAQ below.

       Example:  must have an soname of libyours- and a file name of something/
       and any symlinks pointing directly to this DSO should have
       path/ as the name.  This is a standard sort
       of DSO versioning/naming with Linux-derived DSOs for example.  The
       soname/filename matching requirement is IRIX specific.  If the names
       mismatch the error will not be noticed until rld tries to find the

       Adding .1 or the like according to SGI versioning (as described in
       the previous example and in more detail below in the FAQ area) is
       possible but not normally done with this version-embedded-in-name

       If the DSO is not one you build, you must be sure any file names and
       symlinks you set up naming the DSO match the built-in soname, as the
       soname is what will be used by the static linker (ld) to notify the
       run-time-linker (rld) what file-name to use to find the DSO.

       dlopen is more forgiving and sonames are not crucial. But
       nonetheless it is important you use -soname and file names as if you
       were using linking, not dlopen to access the DSO, as if you do
       change your mind the inability to run against a dso with an improper
       soname will seem mysterious and will involve a waste of your time
       tracking the problem down.

     * If you reference one of the graphics libraries, either or, put the library last in the link line.  Often
       cannot be Quickstarted.  Putting it last allows all prior objects to
       be Quickstarted.  You can also choose to delay-load the graphics
       libraries.  This allows your application to Quickstart.  For
       information on Quickstart, see the PERFORMANCE CONSIDERATIONS
       section of this man page.

     * Anytime a referenced object changes, you should either relink, in
       order to Quickstart, or you should run the reQuickstart tool rqs(1)
       on the object.

     * Try to minimize inter-DSO data references.

     * Try to minimize the use of global data.  In DSOs, it is generally
       more efficient to allocate space when needed, using malloc(3C) or
       malloc(3F), rather than to use a large static data structure.

     * Try to pack data together that is likely to be unmodified.  This
       allows the kernel to make more of the data pages shared,

     * Use the -delay_load option on any DSO on the link line that is not
       often used.  This incurs a small performance penalty for the
       references to it, but this can save time and memory for those
       programs that don't use it.  In addition, using this option on
       programs that have -init or -fini code also incurs a performance

     * Do not call any of the following from code that may be executed
       during processing by the -init or -fini options:  dlclose(3C),
       dlerror(3C), dlopen(3C), dlsym(3C), nsproc(2), sproc(2), sprocsp(2),
       sgidladd(3C), and sgidlopen_version(3C).

     * Avoid having weak and strong versions of a symbol that are loaded
       into memory at different times (by a -delay-load option or by
       sgidladd(3C) or dlopen(3C) calls).

     * Avoid performing a dlclose(3C) on an object that has been opened by

     * Try to avoid using -init code by not using the option and by
       avoiding definition of C++ global objects that require -init code
       for construction.


     The following subsections describe verious performance considerations.

     When building a DSO or an executable, ld(1) assigns addresses to the
     object and attempts to resolve all references.  At runtime, if rld(5)
     verifies that the same set of objects are loaded at the original
     addresses, then rld(5) can skip all the runtime relocation work and
     let the program run.  This saves time because the relocations are not
     performed, and it saves memory because rld(5) does not have to read in
     the sections that hold the relocation information.

     At static link time, ld(1) resolves each unresolved function call.
     When an unresolved function is called at runtime, rld(5) performs the
     relocation needed for all future calls to the original function.  In
     this way, more programs can Quickstart even if some of the function
     references are not resolved at static link time.

     Quickstart fails if the DSOs on a system do not match the objects used
     when linking either the application or the DSOs upon which the
     application depends.  This can occur if a new version of a DSO is

     You can use the rqs(1) command to recalculate the Quickstart
     information associated with an application or a DSO.  rqs(1) must be
     called in proper order so that DSOs on an object's liblist are
     reQuickstarted before the object is reQuickstarted.  rqs(1) rewrites
     the object it is reQuickstarting back in place.  You can use the ld(1)
     command's -no_rqs option to mark an object as non-reQuickstartable.

   Avoiding Gratuitous Shared Object Loads
     rld(5) does a considerable amount of work and can use up large amounts
     of real memory, so it is better not to link against DSOs that are not

   Reducing the Number of Conflicts
     A conflict arises whenever more than one DSO (including the main
     program) needed by an executable defines and uses the same name for a
     symbol.  The name for which multiple definitions exist is recorded in
     your program in the section named .conflict.  The names of all
     conflicting symbols pertaining to a program can be obtained by using
     -Dc flag to elfdump(1).  One example of a conflict is the malloc
     routine, which is defined both in and in

     Conflicts represent extra work to be done at startup because the
     presence of a conflict means that the objects in the link may not have
     chosen a consistent instance of the symbol in question.  This extra
     work is memory-intensive because even one conflict can mean that many
     pages of memory must be examined by rld(5).  This intensive
     examination would otherwise not be needed for a Quickstarting program.
     The ld(1) command's -quickstart_info option causes ld(1) to issue a
     warning about every conflict it finds and to write the names of two of
     the objects in which it is defined.  Of course, sometimes conflicts
     are a necessary design component of certain applications.

   Delayed Loads
     The overhead associated with objects that are referenced but seldom
     used can be mitigated by using dlopen(3C), sgidlopen_version(3C),
     sgidladd(3C), or delayed loads.  Using any of these delays the loading
     of a DSO (and the objects on its liblist) until it is actually
     referenced.  The -delay_load option on the ld(1) command is the
     easiest and most convenient to use.  All three require that there be
     no references from any other object's data section to the delay-loaded


     This section contains answers to frequently asked questions.  The
     questions and their answers are as follows:

     1. What is a DSO?

     DSO stands for Dynamic Shared Object.  DSOs give applications the
     ability to share the text of heavily used libraries, which need not be
     included in the executable file.

     2. How do I maintain binary compatibility between versions of DSOs?

     Binary compatibility is maintained as long as the DSOs maintain the
     same exported symbols, add new symbols without removing any or
     changing semantics, and don't change exported structures.  The
     ordering of symbols, routines, and global data is irrelevant.

     3. What object file format do DSOs use?

     DSOs use the ELF object file format as defined in the SVR4 ABI.

     4. How do I install the tools so I can use DSOs on my system?

     To compile and build DSOs, you need to nstall the IRIX Development
     Foundation (IDF) and the IRIX Development Libraries (IDL); these were
     formerly known as the Developer's Option.  In addition, you must have
     a compiler.

     5. How do I build an executable file that uses a DSO?

     A command line like the following links myfile.c with and

          cc myfile.c -lmine

     If is not available, but libmine.a is available, libmine.a
     is used along with, and you get dynamic linking.  To
     explicitly state that you want the DSO to be used, add the
     -call_shared option to the cc(1) line, as follows:

          cc -call_shared myfile.c -lmine

     6. How do I build an executable file that does not use shared linking?

     Use the -non_shared option, as follows:

          cc -non_shared myfile.c -lmine

     Some libraries are not available as nonshared.  The ones that are
     available are not installed by default, so you must request their
     installation.  In general, the -non_shared option is outmoded.

     7. How do I tell if an executable file will use dynamic linking?

     Entering the following command generates the ELF program header:
          elfdump -o executable

     This header contains all the information necessary for exec(2) and
     rld(5) to run the program or DSO.  Only a.out files that use dynamic
     linking have a PHDR, INTERP, or DYNAMIC entry.  An example and a more
     detailed description is as follows:

          % elfdump -o /bin/cat
           ***** PROGRAM EXECUTION HEADER *****
          Type              Offset      Vaddr       Paddr
          Filesz            Memsz       Align       Flags

          PT_PHDR           0x34        0x10000034  0x10000034
          0xe0              0xe0        0x4         r---

          PT_INTERP         0x114       0x10000114  0x10000114
          0x15              0x15        0x1         r---

          PT_MIPS_OPTIONS   0x130       0x10000130  0x10000130
          0x80              0x80        0x8         r---

          PT_MIPS_REGINFO   0x1b0       0x100001b0  0x100001b0
          0x18              0x18        0x4         r---

          PT_DYNAMIC        0x1c8       0x100001c8  0x100001c8
          0x118             0x118       0x4         r---

          PT_LOAD           0           0x10000000  0x10000000
          0x3000            0x3000      0x4000      r-x-

          PT_LOAD           0x4000      0x10014000  0x10014000
          0x1000            0x1414      0x4000      rw--

     Each type is an entry in the program header and refers to a segment of
     the file, as follows:

     Type      Segment

     PT_PHDR   Points to the program header itself within the file.  Only
               executable files that use dynamic linking have this field.

     PT_INTERP Points to the location of the name of the interpreter
               required for this program.  For any old 32-bit ABI object,
               compiled with -32, this is /usr/lib/  For any new
               32-bit ABI object, compiled with -n32, this is
               /usr/lib32/  For any 64-bit ABI object, compiled
               with -64, this is /usr/lib64/

               Points to the location of the register setup information.
               This information can be seen by entering the elfdump -reg
               command.  For the old 32-bit ABI, obtained when compiling
               with -32, this consists of the correct global pointer (gp)
               value for this object.  For the new 32-bit or 64-bit ABIs,
               obtained when compiling with -n32 or -64, this entry does
               not appear in this table; for these ABIs, the information is
               in .MIPS.options, which can be seen by entering the
               elfdump -reg or elfdump -op commands.

               Points to information in the file needed by rld(5).
               Includes the liblist (which can be seen by entering the
               elfdump -Dl command), a symbol table (which can be seen by
               entering the elfdump -Dt command), and other information.

     PT_LOAD   Points to segments that are to be mapped into the memory

     PT_RWX    Specifies the protections, read, write, or execute, for the

     The columns give various information about each segment, as follows:

     Column    Content

     Offset    The offset in the file to the beginning of the segment.

     Vaddr     The virtual address of the beginning of the segment in the
               memory image of the file, assuming that it was mapped as
               described in the LOAD entries.

     Paddr     The same as Vaddr.

     Filesz    The size of the segment in the file.

     Memsz     The size of the segment in the memory image.  When Memsz is
               greater than Filesz, the bytes after Filesz are zero-filled.

     Align     The alignment required by this section.  If a segment is to
               be mapped somewhere into memory other than at Vaddr, the new
               address must be congruent to Vaddr modulo the alignment.  In
               the preceding example, both segments must always be loaded
               on a 64K (0x4000) byte boundary.

     Programs that are linked with the -non_shared option on the compiler
     command line do not have a PHDR, INTERP, or DYNAMIC section.  Thus,
     the elfdump -o command is a convenient way to determine whether a
     program is linked as nonshared.  For more information on this command,
     see the elfdump(1) man page.

     8. How do I build a DSO?

     Perform the following steps:

     1. Build a file.o or file.a that contains all the routines you want to
        have in your (your DSO).  This can be done with a compiler
        and ar(1).

     2. Invoke ld(1) with the -shared option.  Normally, the extension .so
        is used to designate DSOs.

     Example 1:

          cc -c myobj.c
          ld -shared myobj.o -o

     Example 2:

          cc -c myobj.c
          cc -shared myobj.o -o

     Example 3:

          <build libmine.a the usual way>
          ld -shared -all libmine.a -o

     The -all option in the third example directs ld(1) to include all the
     routines in the library.  This option is needed because there are not
     undefined references in the program, which is the usual way for ld(1)
     to determine whether to load files from an archive.

     9. Where does the system look for DSOs at runtime?

     The search path for DSOs is acquired in the following order for
     programs compiled with the -32 compiler option:

     1. The path of the DSO if given in the liblist

     2. In any directories specified with the -rpath option when the
        executable file was built

     3. In any directory specified by the LD_LIBRARY_PATH environment
        variable, if it is defined

     4. In the directories in the default path, which is /usr/lib,
        /usr/lib/internal, /lib, /lib/cmplrs/cc, /usr/lib/cmplrs/cc,

     If the _RLD_ROOT environment variable is defined, then its value is
     appended to the front of any path specified by the -rpath option and
     the default path.  _RLD_ROOT itself is a colon (:) separated list.

     For programs compiled with the -n32 compiler option, the rules are
     similar, but the following differences exist:

     * The LD_LIBRARYN32_PATH is used if LD_LIBRARY_PATH is defined.

     * _RLDN32_ROOT is used for the list of paths

     * The default path directory list is /usr/lib32, /usr/lib32/internal,
       /lib32, /opt/lib32.

     For programs compiled with the -64 compiler option, the rules are
     similar, but the following differences exist:

     * The LD_LIBRARY64_PATH is used if LD_LIBRARY_PATH is defined.

     * _RLD64_ROOT is used for the list of paths.

     * The default path directory list is /usr/lib64, /usr/lib64/internal,
       /lib64, /opt/lib64.

     See the rld(5) man page for more details.

     10. What is Quickstart?

     Quickstart is an optimization.  Using an so_locations file, ld(1)
     prerelocates each DSO as if it had been loaded (or linked, which is
     the term often used) by ld(1)) at the address in the so_locations
     file.  If no errors occur at startup, all DSOs map to their Quickstart
     addresses, and rld(5) does not need to perform a relocation pass.
     When new software is installed with inst(1M) or swmgr(1M), rqsall(1)
     changes many DSO virtual addresses, attempting to ensure that all
     registered applications (written to /var/inst/.rqsfiles) can be
     Quickstarted.  At the same time, rqsall(1) updates so_locations.

     If more than one DSO attempts to map to the same address, the IRIX
     kernel moves one of them to an unused address range, and rld(5)
     performs a relocation pass to fix the address references.

     If one or more of the DSOs linked against at static link time has
     changed by the time the program executes, rld(5) performs extra work
     to ensure that symbols have been resolved to their proper value.

     11. What is the /usr/lib/so_locations file?

     After you build a DSO, a file called so_locations is placed in the
     directory with the DSO.  This file is a registry of DSOs.  It
     maintains the default, or Quickstart, addresses of a group of DSOs
     that are guaranteed to never have their default locations overlap with
     one another.  It is generated and updated by ld(1) each time it builds
     a DSO.

     If you make substantial library changes between one build of the
     library and another, you should remove the so_locations file before
     rebuilding the library.  You do this because the information derived
     from the older build and put in the so_locations files can make the
     new library build unsuccessful.

     rqsall(1) and rqs(1) can rearrange a.out files and DSOs to restore
     Quickstartability, so the so_locations file is less important than it
     was before rqs(1) existed. For information on address ranges, see the
     following files:  /usr/lib/so_locations, /usr/lib32/so_locations, and

     /usr/lib/so_locations applies to programs compiled with the -32
     compiler option.  /usr/lib32/so_locations applies to programs compiled
     with the -n32 compiler option.  /usr/lib64/so_locations applies to
     programs compiled with the -64 compiler option.  These files represent
     the default layout for the system DSOs in the respective ABIs.  Those
     who build DSOs may find it interesting to consult these files in order
     to avoid collisions between their DSOs and system DSOs.  You do not
     need to consult this file if you merely run programs that use DSOs.

     If you build DSOs, three ld(1) command options may be useful to you:
     -create_registry, -check_registry and -update_registry.

     * create_registry registry_file creates a registry file for the DSO
       being linked. This will always overwrite registry_file if it exists
       and create it if it does not exist. This option instructs the linker
       not to reference any registry file for layout specifications.

     * update_registry registry_file reads registry_file for any layout
       specifications for the DSO being linked. Update registry_file with
       layout information for the DSO being linked. If egistry_file doesn't
       exist, it creates it.

     * check_registry registry_file reads registry_file for any layout
       specifications for the DSO being linked. It is an error if
       registry_file doesn't exist. This option will not alter

     The default behavior without the any of the above options is to
     neither read nor write a registry file.

     12. What directives can be put into a so_locations file?

     The following directives control the placement of new DSOs:

     * $start_address=addr: Specifies the beginning address for DSOs.

     * so_name[:st={.text|.data|$range]} base_addr,pad_size:]: This
       directive consists of the following elements:

       Element     Composition

       so_name     Full path name (or trailing component) of a DSO.

       st          String that identifies the start of the segment

       .text or .data or $range
                   Specify either a segment type, text or data, or a range.
                   Specifying a range limits the range of addresses that
                   can be used.  Use the $range form  not the .text or
                   .data forms whenever you write or modify an so_locations

       base_addr   Address at which the segment starts.

       pad_size    Padded size of the segment.

     When building a DSO with the -check_registry or -update_registry
     linker option, the following fatal errors may occur:

     * .text or .data are specified, but those segments overlap due to
       segment size.

     * .text or .data are specified along with $range, but the segments of
       that DSO cannot fit within the specified range.

     * $range is specified, but the segments of that DSO cannot fit within
       the specified range.

     A comment line can be inserted at any point a directive can be
     inserted.  A comment is a line beginning with the number sign (#)

     13. If I don't have a valid so_locations file, can I generate one from
     all the .so files in /usr/lib?

     Not easily.  It is an error if the so_locations is missing.  Every
     so_locations file is different because rqsall(1) reQuickstarts

     If /var/inst/.rqsfiles is present, you could get a set of so_locations
     files from a similar system and rerun rqsall(1) as inst(1M) and
     swmgr(1M) do.  If you do this, make a back-up copy of .rqsfiles before
     starting rqsall(1).

     NOTE: If anything destroys or results in the loss of .rqsfiles, the
     only way to recreate .rqsfiles is to reinstall everything on the
     system.  Make a back-up copy of .rqsfiles.

     14. How expensive is it, at runtime, NOT to use the -update_registry

     If you use rqsall(1) or rqs(1) to reQuickstart an application and its
     DSOs, then there need not be any cost.  rqs(1) can make the DSOs
     Quickstartable regardless how the DSO addresses were determined.

     If you do not use rqs(1), then the lack of an updated registry can
     impose startup costs.  It is very difficult to say how much a
     particular executable will suffer because it depends on which DSOs the
     program uses and whether they have been Quickstarted for the same
     address.  When there is a conflict between two objects, one will be
     moved, which means that all addresses referring to names in that
     object need to be relocated.  15. How and when will Quickstart be

     The linker uses Quickstart unless there are unresolved symbols at
     static link time.

     Every executable and every DSO contains a list of objects that were
     examined at static link time when the object was made.  This list also
     contains timestamps and checksums for each of the objects.  Various
     levels of extra work are required if the timestamp or checksum changed
     in the library at runtime.

     16. What about runtime loading under user control?

     The library allows you to dynamically load your own DSOs as needed.
     The individual library calls are as follows:

     * dlopen(3C), which opens a DSO.

     * dlsym(3C), which finds the value of a name defined in an object.

     * dlclose(3C), which closes a DSO.

     * dlerror(3C), which reports errors.

     * sgidladd(3C), which functions much like dlopen(3C), but it exposes
       all symbols to the rest of the program.

     * sgidlopen_version(3C), which functions much like dlopen(3C), but it
       allows specifying a specific required version of the DSO.

     Consult the individual man pages for details.

     17. What benefits will I get from DSOs?

     Executables linked with DSOs are smaller because the DSOs are not part
     of the executable file image.

     Executables that use a DSO need not be relinked if a DSO is changed.
     After the updated DSO is installed, the executable picks it up

     DSOs allow application designers to make more machine-independent
     software.  System-dependent routines can be given a uniform interface,
     and a DSO that implements that interface can be built for each
     different platform.  Actual applications can be shipped to various
     platforms and run on them all.

     DSOs give applications the ability to change the binding of symbols at
     runtime and under user control.

     18. What costs are associated with DSOs?

     A DSO incurs two costs, both against performance.

     The first is a start-up cost incurred while rld(5) maps in the various
     objects, performs symbol resolution, etc.  This cost is usually small
     compared to the time it takes to contact the X server, for example.

     The second is the cost incurred when using position-independent code.
     A DSO's text must be compiled with the -KPIC option in effect in order
     for the object file to be put into a DSO without further modification.
     Because this option is in effect by default, it is not necessary to
     specifiy it.  By default, PIC is slower by 5% to 15%.  With full
     optimization, however, the speed reduction can be near zero.  PIC code
     seems to be worst on very small-leaf routines that access global data.

     Routines written in assembly language for non-PIC use (for example,
     routines written before PIC was available for IRIX) need to be
     modified before the -KPIC option can be used.  For more information on
     modifying your code, see the MIPSpro Assembly Language Programmer's

     19. Must main programs that want to use DSOs use -KPIC for

     Yes.  DSOs use -KPIC so that PIC code is generated.  Main programs are
     not generally position-independent, but they must still use the DSO
     calling convention when calling a routine that is defined in a DSO.
     In particular, this means that a main program must have a Global
     Offset Table (GOT) and the code that is generated must use it.

     Modules that will become part of main programs and modules that become
     part of DSOs must be compiled with the -KPIC option in effect, which
     is enabled by default.

     20. What options do I have when building a DSO?

     If you specify the -B dynamic option while linking a DSO, symbols in
     the DSO are resolved in a nondefault manner.  In particular, the
     runtime linker first tries to resolve symbols referenced in the object
     to symbols defined in the object instead of looking for definitions in
     objects in the order specified on the link line.

     The effect is that all symbols defined and used in such objects are
     non-preemptable.  Ordinarily, symbol definitions could be preempted by
     a definition in an earlier DSO.  When -B symbolic is specified,
     however, this is not the case.

     For more information on the -B dynamic and -B symbolic options, see
     the ld(1) man page.

     21. What difficulties may be associated with DSOs?

     Behind most unexpected behavior is the fact that linking semantics are
     fundamentally different, but only in a subtle way.  Assume that a
     program links with three libraries, libA, libB, and libC, in that
     order.  Further assume that both libA and libC define symbol x but
     don't use it.  Further, assume that libB contains a reference to x.
     Archive linking (the old way) would resolve libB's reference to x to
     the definition in libC, whereas DSO linking resolves libB's reference
     to x to the definition in libA.  This is true because with archive
     linking, when libA is examined, there is no outstanding reference to
     x.  The definition of x is not extracted from the archive.  Later,
     when libC is examined, there is a reference to x, so it is loaded.

     With DSOs, all the constituent object files have been joined into one
     object, so all symbol definitions are always present.  The resolution
     rule is simple: take the definition in the object listed first.  Thus,
     the definition in libA is used.

     Another unexpected occurrence is a runtime dangling reference.  These
     occur when you build and link an application with no errors or
     warnings but later receive a message from rld(5) stating that your
     program has unresolvable symbols.

     The problem here is that if you build a DSO as part of your program,
     the linker typically does not generate messages about undefined
     symbols during a link of a DSO.  This is because undefined symbols are
     expected during such a build and are perfectly acceptable.  If the
     main program does not use a symbol, however, it is not flagged as
     undefined during static linking.  You can use the -no_unresolved
     option to the ld(1) command to avoid such unexpected behavior.

     If a particular object in an archive file (libl.a, for example) has an
     external reference to a data symbol, and the data symbol is expected
     to be defined in the main program, the linker does not try to resolve
     that external reference unless the object file in question was
     actually referenced by the main program.  If that archive is turned
     into a DSO, the external data reference must be resolved whenever ANY
     function in the DSO is used, even if no function in the object file in
     question is ever called and no use is made of the external data symbol
     in question.

     This can lead to a scenario in which a link that worked with the
     archives builds a program that is terminated by the runtime linker
     (rld(5)).  Do not assume that you can convert libraries that contain
     external data symbols into DSOs.

     One remedy is to split the archive into several DSOs and place them on
     the liblist of a master DSO.  By default, rld(5) does not try to
     resolve data symbols until the first call is made to a particular
     object.  You can, however, inhibit the linker's attempt to resolve an
     offending external data symbol until a call is made to the object in
     which it is referenced.  For example, suppose that ext_data.o is an
     object that contains an undefined external reference.  It resides in
     archive libxyz.a.  Here is how to isolate that external data

     1. Make ext_data.o into a DSO all its own:

          % ar x libxyz.a has_ext_data.o
          % ld -shared ext_data.o -o

     2. Make, excluding ext_data.o from being included directly.
        Instead, put it in the liblist of

    % ld -shared -all -exclude ext_data.o libxyz.a -o

     In addition to the previously mentioned caveats, applications should
     not call dlopen(3C), sgidladd(3C), dlclose(3C), sgidlopen_version(3C),
     or dlerror(3C) from within a signal handler.  This means that calling
     from within a signal handler calling a function that results in a DSO
     being delay-loaded is also wrong.  Ensure that functions called
     (directly or indirectly) from signal handlers are already loaded
     before a signal handler is set up.  Very few functions are safe to
     call from within a signal handler (POSIX specifies a few), and the
     delay-load functions (dlopen(3C), and so on) are not among them.

     22. What should I do about Global Offset Table (GOT) overflow?

     GOT overflow has occured if you receive messages from the linker
     saying GP-relative sections overflow by 0x??? bytes, GOT overflow, or
     GOT unreachable.

     To fix this situation, perform one of more of the following steps:

     * Break the large input file.o into two or more smaller files.

     * Use the -m option on the ld(1) command to obtian a link map.  This
       map indicates large objects that you can recompile with -G0 or some
       other small -G value.

       Data objects affected by the -Gnum option are numeric literals,
       addreses (including those generated by the compiler), all C/C++
       static veriables, and, if the -static option is in effect, all
       Fortran local variables.  For more information on the -Gnum option,
       see your compiler command line.

     23. How are multiple versions of DSOs supported?

     You can associate DSOs and executables with a version number.  This is
     intended to support interface changes.

     A version string consists of 3 parts and a period (.), as follows.
     The first part is the string sgi.  The second part is a decimal
     number, which is the major number.  The third part is the period (.).
     The fourth part is a decimal number, which is the minor number.  Hence
     the format:  sgimajor.minor.

     For a DSO to be versioned as sgi1.0, add the -set_version sgi1.0
     option to the compiler or loader command line to build the DSO (cc -
     shared, ld -shared, and so on).

     Whenever you make a compatible change, update the minor version number
     (the one after the period) and add the latest version string to
     colon-separated list of version strings.  For example:
     -set_version sgi1.0:sgi1.1:sgi1.3.

     Whenever you make an incompatible change, update the major version
     number.  For example, use -set_version sgi2.0.  Change the file name
     of the old DSO by adding a period followed by the previous major
     number to the file name of the DSO.  Do not change the soname of the
     object.  No change to the file contents are necessary or desirable.
     Simply rename the file.

     24. How does versioning work?

     Note that in this answer, items marked SGI ONLY do not apply to MIPS
     ABI binaries; they apply only to binaries generated on IRIX systems
     using a means other than the abicc(1) or abild(1) commands.

     Versioning is available for NON-ABI executables only.  The ABI does
     not require objects to have versioning, nor does it require systems to
     recognize versioning.  It allows objects to contain version strings,
     but it does not require systems to do anything with this information.

     NON-ABI compliant executables have the RHF_SGI_ONLY bit turned on in
     the .dynamic section.  This flag is reported by the elfdump(1) command
     when elfdump -long  -L is entered.  Only executables with this flag
     turned on receive the versioning treatment described in this answer.
     RHF_SGI_ONLY is turned on by default.

     When an executable is linked against a DSO, the last entry of the
     DSO's version string is recorded in the executable as part of the
     liblist.  This can be examined by using the -Dl option to the
     elfdump(1) command.

     When an executable is linked, you may specify the -require_minor or
     -ignore_minor options for each DSO linked against.  If -require_minor
     is specified, a bit will be set in the flags field of the liblist
     entry for the DSO in question.  The default is -ignore_minor.

     When an executable (ABI or RHF_SGI_ONLY) is run, rld(5) searches for
     the proper file name in its usual search routine.

     (SGI_ONLY) If a file with the correct name is found, the version
     string in the liblist is compared to the list of version strings in
     the DSO.  If the LL_REQUIRE_MINOR bit is set in the liblist entry and
     there is an exact match between the version string in the depender and
     one of the strings in the version list of the dependee, then that
     library is used.  If the LL_REQUIRE_MINOR bit is clear and if there is
     a match of major versions, then that library is used.

     (SGI_ONLY) If no proper match is found, a new soname is built by
     taking the soname found in the executable's liblist and the major
     number found in the version string that corresponds to that liblist
     entry.  They are put together as soname.major.  This is searched for
     as described previously.  Version strings are matched as described

     (SGI ONLY) If, for example, has a liblist entry with a version
     list for and an is loaded that has no version, the DSO is
     considered a match.  If has a liblist entry with no version list
     for, then the first found is considered a match, no matter
     what version is.  File with no version can be created, for
     example, if ld(1)'s -set_version option was not used or if an empty
     string was provided as an argument to the -set_version option.

     (SGI ONLY) A version string with a missing major number is an error.
     rld(5) behavior is not defined for such cases.

     25. Why are the global objects in my C++ DSO not being initialized?

     Did you link your DSO using the CC(1) command instead of using ld(1)
     directly?  See the C++ information in the LINKING AND BUILDING SHARED
     OBJECTS section of this man page.

     26. Why are some libraries only available as a DSO whereas other
     libraries are available as both a DSO and an archive?

     The ABI specifies the DSOs that must be on every system.  The converse
     of that is that no one can assume that any other .so is on an ABI-
     conforming system.  Libraries explicitly called out in the MIPS ABI
     are considered part of the system interface.  Such libraries are
     shipped only in DSO form.  Libraries that are not specified in the
     MIPS ABI must also be supplied in archive form to generate MIPS ABI
     compliant binaries using these libraries.

     For example, the libraries and are explicitly
     called out in the MIPS ABI.  This makes the DSO version of Xlib and
     libc a system interface.  Other examples are and, which are also only supplied as DSOs.

     Archive versions of libXt.a, libXm.a, libm.a, libmalloc.a, and others
     are supplied because shared library versions of these libraries are
     not specified in the MIPS ABI.  Therefore, they are not guaranteed to
     exist on all ABI conforming systems.

     27. What are symbol binding problems?

     Symbol binding, also known as name resolution, is the process of
     determining the data or function to use for an external name
     reference.  If you are developing executable files or DSOs, you need
     to address this topic, but if you are simply running predeveloped
     applications, you can assume that symbol binding has been resolved for

     All symbols for which there is only one definition are simple.  The
     one and only definition is used.

     For global references, the general approach is to examine the set of
     DSOs on the list that rld(5) builds at run time and to use the first
     definition found.  If there is a weak definition, then the first of
     those is taken if and only if there is no strong definition.  If there
     is a strong definition, which might better be called a typical
     definition, the strong definition is used.  In C and C++, #pragma weak
     is used to create a weak reference or definition.

     Typically, DSOs are added to rld(5)'s list in breadth-first order,
     generating the transitive closure of all DSOs on the executable
     liblist (as shown by the elfdump -Dl command).

     If the application calls sgidladd(3C) or has any delay-loaded DSOs,
     those DSOs are added to the end of rld(5)'s DSO list when they are
     actually loaded.  If the loading is different with different data
     (that is, if the application calls functions that cause sgidladd(3C)
     or -delay-load operations in a different order at different times),
     the list of DSOs may be not have the same ordering.  If there are
     multiple definitions, the first definition on rld(5)'s list of DSOs
     for the executable is be used.

     If all definitions are weak definitions, the resolution proceeds
     conceptually identically to the strong case.  If there is at least one
     strong and one weak definition of a symbol things, resolution proceeds
     as follows:

     1. If a strong definition is in a DSO loaded into memory, it
        supersedes any weak definitions loaded.

     2. If a weak definition is loaded and no strong definition is loaded,
        the weak definition is used.  If an sgidladd(3C) or -delay-load
        operation causes a strong definition to be loaded, the symbol may
        or may not be rebound to the new strong definition.  To avoid this
        unpredictable behavior, you may need to relink or rewrite your
        program with the following aspects of symbol resolution in mind:

        * You may obtain unexpected results if a strong symbol definition
          is loaded after a weak definition.  In these cases, some calls
          may refer to one version and some to another, possibly within the
          same execution.

        * The order in which your executable calls functions or performs
          sgidladd(3C) or delay-load operations can affect symbol

        * Symbols that remain undefined after linking can affect symbol

     3. Weak symbols were defined to allow ISO/ANSI C program to, for
        example, implement their own write() operation while not affecting
        the operation of fwrite() and other ISO C calls and while still
        allowing another application to choose to call the libc write()
        routine.  It was expected that the strong symbol would be visible
        at the same time as the weak symbol.  If both are visible at the
        same time they work predictably.  But, as explained previously, if
        the weak symbol is visible when the strong symbol is not, the
        program can exhibit unexpected and unpredictable behavior.

     28. Are there negative aspects to using dlclose(3C)?

     Because of symbol definition order rules, do not perform a dlclose(3C)
     on a DSO that was initially opened by a call to sgidladd(3C).  For
     more information on this, see NAMESPACE ISSUES on the dlopen(3C) man


     cc(1), CC(1), elfdump(1), f90(1), f77(1), ld(1)

     exec(2), nsproc(2), sigprocmask(2), sproc(2), sprocsp(2)

     dlclose(3C), dlerror(3C), dlopen(3C), dlsym(3C), malloc(3C),
     malloc(3F), pthread_mutex_lock(3P), setlocale(3C), sgidladd(3C),
     sgidlopen_version(3C), sgigetdsoversion(3C)

     capabilities(4), capability(4)

     abi(5), gp_overflow(5), rld(5)

     MIPSpro N32/64 Compiling and Performance Tuning Guide

     MIPSpro 64-Bit Porting and Transition Guide

     MIPSpro Assembly Language Programmer's Guide

home/search | what's new | help