Surfing With a Linker Alien
Rod Evans's Weblog
All | General | Solaris

20061013 Friday October 13, 2006

Displacement Relocation Warnings - what do they mean?

There have been a couple postings recently regarding relocation warnings that have been observed when using the link-editors -z verbose option. The first warning originates from building a shared object:

    ld: warning: relocation warning: R_SPARC_DISP32: file shared.o: \
        symbol <unknown>: displacement relocation applied to the \
        symbol __RTTI__1nEBase_: at 0x8: displacement relocation will \
        not be visible in output image

Then, if this shared object is referenced as a dependency when building a dynamic executable, another warning can be generated:

    ld: warning: relocation warning: R_SPARC_COPY: file shared.so: \
        symbol xxxx: may contain displacement relocation

These warnings stem from an old request from the compiler folks to help prevent problems with displacement relocations and copy relocations.

You have to be a little relocation savvy to understand these scenarios - they make my head hurt. Investigations are underway to determine why these warnings are starting to surface.



Technorati Tag: OpenSolaris
Technorati Tag: Solaris

(2006-10-13 14:24:56.0) Permalink

Dynamic Object Versioning - specifying a version binding

After reading a previous posting on versioning, a developer asked how they could specify what version to bind to when they built their application. For example, from the version definitions within libelf.so.1:

    % pvs -d /lib/libelf.so.1
        libelf.so.1;
        SUNW_1.5;
        SUNW_1.4;
        ....
        SUNWprivate_1.1;

how could you restrict an application to only use the interfaces defined by SUNW_1.4. Note, version SUNW_1.4 inherits previous versions.

The Linker and Libraries Guide covers this topic in the section Specifying a Version Binding. In a nutshell, you can specify a version control mapfile directive:

    % cat mapfile
    libelf.so - SUNW_1.4;

Notice that the shared object name is the compilation environment name. This is the name that gets resolved when you specify -lelf. By adding this mapfile to your link-edit, the link-editor will restrict the interfaces you are able to bind to from libelf to those provided by version SUNW_1.4.

Note, if you build against libelf.so.1 and discover a dependency on SUNW_1.5, then you are referencing interfaces from the SUNW_1.5 version. These will show up as undefined errors if you build an application using the version control mapfile directive. You'll have to recode your application to not use the SUNW_1.5 interfaces.

For example, this application is referencing gelf_getcap(3ELF).

    % pvs -r prog
        libelf.so.1 (SUNW_1.5);
        ....
    % pvs -dos /lib/libelf.so.1 | fgrep SUNW_1.5
        /lib/libelf.so.1 -      SUNW_1.5: gelf_getcap;
        /lib/libelf.so.1 -      SUNW_1.5: gelf_update_cap;

Note also, binding to specific versions is not a panacea for building software on release N and running on N-1. Other factors can affect your build environment, such as headers. It is always safest to build your software on the oldest platform on which it is intended to run.

Of course, building on the latest release can provide a richer debugging environment in which to develop your software. I often try building things on the latest environment, and then fall back to the oldest environment for final testing and for creating final deliveries.



Technorati Tag: OpenSolaris
Technorati Tag: Solaris

(2006-10-13 10:48:22.0) Permalink

20061004 Wednesday October 04, 2006

Changing Search Paths with crle(1) - they are a replacement

A developer who wished to add /usr/sfw/lib to their default runtime search path, managed to turn their system into a brick by using crle(1):

    # crle -l /usr/sfw/lib
    # ls
    ld.so.1: ls: fatal: libsec.so.1: open failed: No such file or directory
    Killed

The problem was that crle(1),in this basic form, created a system wide configuration file. This configuration file defined that the default runtime search path for shared object dependencies is /usr/sfw/lib. This search path definition had replaced the standard defaults.

You can determine the standard search path defaults using crle(1).For example, without any system wide configuration file, the following defaults might exist:

   $ crle

   Default configuration file (/var/ld/ld.config) not found
     Platform:     32-bit LSB 80386
     Default Library Path (ELF):   /lib:/usr/lib  (system default)
     Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

This user had effectively removed the system default search paths, and hence the runtime linker, ld.so.1,had been unable to find the basic dependencies required by all applications. The new configuration file revealed:

   $ crle

   Configuration file [version 4]: /var/ld/ld.config
     Platform:     32-bit LSB 80386
     Default Library Path (ELF):   /usr/sfw/lib
     Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

   Command line:
     crle -c /var/ld/ld.config -l /usr/sfw/lib

The -l option allows you to define new search paths. However, rather than dictate that a new search path definition be prepended, inserted, or appended to any existing search paths, crle(1) simply replaces any existing search paths. The man page spells this out in some detail:

    -l dir
      ....
      Use of this option replaces  the  default  search  path.
      Therefore,  a  -l option is normally required to specify
      the original system default in relation to any new paths
      that are being applied. ....

Therefore, to prepend the new search path to the existing defaults you should specify each search path:

    # crle -l /usr/sfw/lib -l /lib -l /usr/lib
    # ls
    devices/        lib/            proc/
    ....

An alternative is to use the -u, update, option. Any new search paths supplied with crle(1) are appended to any existing search paths. Even if an existing configuration file does not exist, the -u option causes any new search paths to be appended to the system defaults:

   # crle -u -l /usr/sfw/lib
   # crle

   Configuration file [version 4]: /var/ld/ld.config
     Platform:     32-bit LSB 80386
     Default Library Path (ELF):   /lib:/usr/lib:/usr/sfw/lib
     Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

   Command line:
     crle -c /var/ld/ld.config -l /lib:/usr/lib:/usr/sfw/lib

Note that the usage message from crle(1) is a little misleading, as it implies that the new search path is an addition:

   # crle -X
   crle: illegal option -- X
       ....
       [-l dir]        add default search directory
       ....

We'll get the usage message updated to be more precise.

Remember, should you ever get in trouble with crle(1) configuration files, you can always instruct the runtime linker to ignore processing the configuration file by setting the environment variable LD_NOCONFIG=yes:

   # crle -l /does/not/exist
   # ls
   ld.so.1: ls: fatal: libsec.so.1: open failed: No such file or directory
   Killed
   # LD_NOCONFIG=yes ls
   devices/        lib/            proc/
   ....
   # LD_NOCONFIG=yes rm /var/ld/ld.config
   # ls
   devices/        lib/            proc/
   ....

It is recommended that when creating a new configuration file, you first create the file in a temporary location. The environment variable LD_CONFIG can then be set to this new configuration file. Refer to the crle(1) man page for an example.

Note. crle(1) should not be crippled by blowing away the system default search paths:

   # crle -l /does/not/exist
   # crle

   Configuration file [version 4]: /var/ld/ld.config
     Platform:     32-bit MSB SPARC
     Default Library Path (ELF):   /does/not/exist
     Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

   Command line:
     crle -c /var/ld/ld.config -l /does/not/exist

   # elfdump -d /usr/bin/crle | fgrep RPATH
   ld.so.1: fgrep: fatal: libc.so.1: open failed: No such file or directory
   ksh: 18184 Killed
   # LD_NOCONFIG=yes; export LD_NOCONFIG
   # elfdump -d /usr/bin/crle | fgrep RPATH
      [6]  RPATH             0x61b               $ORIGIN/../lib

Using $ORIGIN within a runpath provides crle(1) with a level of protection against insufficient configuration file information.



Technorati Tag: OpenSolaris
Technorati Tag: Solaris

(2006-10-04 14:48:41.0) Permalink Comments [1]


archives
links
referers