Real Name · Soname · Linker Name — Understanding the Naming Convention
Why Do Shared Libraries Have Three Names?
When you write a C program on Linux and link it against a library like libreadline, multiple files with slightly different names are involved. This is not an accident — it is a carefully designed system that allows:
- Backward compatibility: Old programs continue to work even after library updates
- Multiple major versions: libdemo version 1 and version 2 can coexist on the same system
- Automatic minor upgrades: When a bug-fix release comes out, programs automatically pick it up at runtime without recompilation
- Version-independent linking: You write -ldemo in your build command — no version numbers needed
To achieve all this, Linux uses three distinct names for each shared library. Understanding these is fundamental to every embedded Linux and systems programmer.
The real name is the actual file on disk that contains the compiled library code. It uses the naming format:
Major version identifier: An integer that is incremented every time the library makes an incompatible change (e.g., removed functions, changed function signatures). Programs built against version 1 cannot use version 2 automatically.
Minor version identifier: A number (or two dot-separated numbers for patch level) that is incremented for compatible changes — bug fixes, new functions added (but old ones not removed). A program built against version 1.0.1 can use version 1.0.2 without recompilation.
Examples of real names:
| Real Name | Major | Minor | Meaning |
|---|---|---|---|
| libdemo.so.1.0.1 | 1 | 0.1 | First major release, patch 1 |
| libdemo.so.1.0.2 | 1 | 0.2 | Compatible with 1.0.1 (minor update) |
| libdemo.so.2.0.0 | 2 | 0.0 | Incompatible with version 1.x |
| libreadline.so.5.0 | 5 | 0 | readline library, major 5 |
The soname (shared object name) has only the major version number — it drops the minor version. Format:
The soname is a symbolic link (not a real file) that points to the most recent minor version within its major version. When you compile and link your program, the linker embeds the soname string inside your executable. At runtime, the dynamic linker reads this embedded soname and resolves it via the symbolic link.
Why this design is powerful:
- The soname libdemo.so.1 can be updated to point from libdemo.so.1.0.1 to libdemo.so.1.0.2 (a bugfix release)
- All existing programs that were linked against libdemo.so.1 automatically get the bugfix without recompilation
- Programs needing version 2 use libdemo.so.2 — both versions coexist safely
Soname symbolic links in practice:
The linker name is the simplest — it has no version numbers at all. Format:
When you write gcc -ldemo in your build command, the linker searches for libdemo.so. This is the linker name. It is a symbolic link that usually points to the soname (which in turn points to the real name).
Linker name examples:
| Name Type | Format | File Type | Used When | Example |
|---|---|---|---|---|
| Real Name | libname.so.maj.min | Regular file (actual code) | At runtime — actual library loaded | libdemo.so.1.0.2 |
| Soname | libname.so.maj | Symbolic link → real name | Embedded in executable; resolved at runtime | libdemo.so.1 |
| Linker Name | libname.so | Symbolic link → soname | At compile/link time (-ldemo) | libdemo.so |
How name resolution flows at compile time and runtime:
At Compile Time (gcc -ldemo):
At Runtime (./prog):
The three-layer naming structure visualized:
|
libdemo.so
Linker Name
(symbolic link)
|
libdemo.so.1
Soname
(symbolic link)
|
libdemo.so.1.0.2
Real Name
(regular file)
|
|
⟶ libdemo.so points to libdemo.so.1 ⟶ libdemo.so.1 points to libdemo.so.1.0.2
|
||
Example 1: Inspect the soname embedded in an executable
# After building a program that links against libdemo.so,
# you can inspect what soname is embedded inside the ELF binary
$ readelf -d prog | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libdemo.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
# The output shows libdemo.so.1 — this is the SONAME embedded at link time.
# Notice: NOT libdemo.so (linker name), NOT libdemo.so.1.0.2 (real name)
# The soname is what gets recorded inside the ELF binary.
Example 2: List all three names of a real system library
# Let's examine libreadline on a typical Linux system
$ ls -l /usr/lib/x86_64-linux-gnu/libreadline*
lrwxrwxrwx libreadline.so -> libreadline.so.8 # linker name
lrwxrwxrwx libreadline.so.8 -> libreadline.so.8.2 # soname
-rwxr-xr-x libreadline.so.8.2 # real name (actual file)
# Pattern:
# libreadline.so --> linker name (no version) → used by: gcc -lreadline
# libreadline.so.8 --> soname (major only) → embedded in executables
# libreadline.so.8.2 --> real name (maj.min) → actual file on disk
Example 3: Create symbolic links for all three names manually
# Suppose you have just compiled libdemo version 1.0.1
# Step 1: You have the real name file (from compilation)
ls libdemo.so.1.0.1
# -rwxr-xr-x libdemo.so.1.0.1
# Step 2: Create the soname symlink (major version only)
ln -s libdemo.so.1.0.1 libdemo.so.1
# libdemo.so.1 -> libdemo.so.1.0.1
# Step 3: Create the linker name symlink (no version)
ln -s libdemo.so.1 libdemo.so
# libdemo.so -> libdemo.so.1 -> libdemo.so.1.0.1
# Verify all three:
ls -l libdemo.so*
# lrwxrwxrwx libdemo.so -> libdemo.so.1 (linker name)
# lrwxrwxrwx libdemo.so.1 -> libdemo.so.1.0.1 (soname)
# -rwxr-xr-x libdemo.so.1.0.1 (real name)
Example 4: Minor version upgrade — update soname pointer
# Library was at version 1.0.1, now 1.0.2 is released (bugfix)
# New real name file exists:
ls libdemo.so.1.0.2
# Update soname to point to the newer minor version:
ln -sf libdemo.so.1.0.2 libdemo.so.1
# ^^ -f forces overwrite of existing symlink
ls -l libdemo.so.1
# lrwxrwxrwx libdemo.so.1 -> libdemo.so.1.0.2 (now points to 1.0.2!)
# All programs that were using libdemo.so.1 automatically get 1.0.2
# No recompilation needed!
# The linker name libdemo.so still correctly points to libdemo.so.1
🎯 Interview Questions — Shared Library Names
libname.so.major.minor; (2) Soname — a symbolic link with only the major version (libname.so.major), embedded in executables and used at runtime; (3) Linker name — a symbolic link with no version (libname.so), used only at compile/link time via -lname.readelf -d <binary> | grep NEEDED — this shows all the sonames the binary depends on.gcc -o prog prog.c ./libdemo.so.1 or gcc -o prog prog.c -L. -l:libdemo.so.1.0.1.libdemo.so.1 and libdemo.so.2). Program A (linked with soname v1) and Program B (linked with soname v2) each load their correct version independently via the dynamic linker.1.0.1 (minor=0, patch=1). Most well-maintained libraries follow this convention.-Wl,-soname,libdemo.so.1 flag passed to gcc. This passes the -soname option to the underlying linker (ld). Example: gcc -shared -Wl,-soname,libdemo.so.1 -o libdemo.so.1.0.1 mod1.o mod2.oldconfig automates the task of creating and updating soname symbolic links to point to the most recent minor version of each major library version. It reads library directories and updates /etc/ld.so.cache. When the linker name is set up to point to the soname, ldconfig implicitly maintains the linker name too.Next: Creating a Shared Library → Part 3: Installing Shared Libraries
