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


14 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.