Understanding Solaris Library Versioning: The Role of .so vs .so.1 Files in Dynamic Linking


2 views

The ".1" suffix in Solaris shared library names like libodbc.so.1 represents the library's major version number. This follows the Solaris (and UNIX) convention of library versioning where:

libname.so.MAJOR.MINOR.PATCH

The version components indicate:

  • .1: Major version (backward-incompatible changes)
  • .0: Minor version (backward-compatible additions)
  • .0: Patch level (bug fixes)

Solaris uses this versioning scheme to maintain multiple versions of libraries simultaneously. When you see:

$ ls -l /usr/lib/libodbc*
lrwxrwxrwx 1 root root     15 Oct 12  2022 libodbc.so -> libodbc.so.1
lrwxrwxrwx 1 root root     19 Oct 12  2022 libodbc.so.1 -> libodbc.so.1.0.0
-rwxr-xr-x 1 root root 123456 Oct 12  2022 libodbc.so.1.0.0

The symlinks create a version hierarchy where applications can request either:

  1. Specific version (libodbc.so.1)
  2. Most current version (libodbc.so)

The Solaris linker (ld.so.1) follows strict rules when resolving library dependencies:

$ ldd -s /usr/local/bin/isql
...
  find object=libodbc.so.1; required by /usr/local/bin/isql
    search path=/usr/lib:/usr/local/lib  (RPATH from file /usr/local/bin/isql)
    trying path=/usr/lib/libodbc.so.1
    trying path=/usr/local/lib/libodbc.so.1
    found libodbc.so.1 at /usr/local/lib/libodbc.so.1

When building shared libraries on Solaris, use the -h linker flag to embed the soname:

$ cc -G -o libodbc.so.1.0.0 -h libodbc.so.1 source.o

Key points for library management:

  • Always create versioned symlinks during installation
  • Major version increments indicate ABI incompatibility
  • Use pkgadd or svcadm for system-wide library updates

For troubleshooting, these Solaris commands are essential:

$ elfdump -d /usr/local/bin/isql | grep NEEDED
$ crle -c /var/ld/ld.config -64
$ LD_DEBUG=all ldd /path/to/binary

Remember that library paths are cached in /var/ld/ld.config - update it after library installations.


On Solaris (and Unix-like systems in general), shared libraries follow a specific versioning convention. The numbers after .so indicate library versioning information. Here's the typical pattern:

libname.so.MAJOR.MINOR.PATCH
libname.so.MAJOR
libname.so

The version components represent:

  • MAJOR version (1 in libodbc.so.1): Indicates backward-incompatible API changes
  • MINOR version: Adds functionality in a backward-compatible manner
  • PATCH version: Backward-compatible bug fixes

The linker looks for specific library versions during dynamic linking. Here's what happens with your example:

ldd /usr/local/bin/isql -s

When the linker searches for libodbc.so.1, it's specifically requesting major version 1 of the library. The actual file might be libodbc.so.1.0.0, with libodbc.so.1 being a symbolic link to it.

Here's how the versioning affects compilation and linking:

# Compile with specific version
gcc -lodbc.1 -o myprogram myprogram.c

# Runtime linking
LD_LIBRARY_PATH=/path/to/libs ./myprogram

Solaris uses this versioning approach to maintain:

  • Backward compatibility
  • Multiple versions of the same library
  • Clean dependency management

To check library dependencies and versions:

# List dependencies
ldd -s /path/to/binary

# View library versions
pvs -d /path/to/library.so

Here's how you might create a versioned library:

# Compile with version information
gcc -shared -Wl,-soname,libtest.so.1 -o libtest.so.1.0.0 test.c

# Create symbolic links
ln -s libtest.so.1.0.0 libtest.so.1
ln -s libtest.so.1 libtest.so

This creates the full version chain that Solaris expects for proper library management.