Fundamentals of Shared Libraries Real Name · Soname · Linker Name — Understanding the Naming Convention

 

Shared Library Names
Chapter 41 — Fundamentals of Shared Libraries (TLPI)
Real Name · Soname · Linker Name — Understanding the Naming Convention
📚
Chapter 41
TLPI — Part 7
🔗
3 Name Types
real / soname / linker
⚙️
Versioning
major.minor.patch
🎓
10 Interview Q
with answers

🔑 Key Terms in This Tutorial
shared library real name soname linker name major version minor version symbolic link libname.so -fPIC ldconfig -Wl,-soname version compatibility

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.

1. The Real Name (libname.so.major.minor)
actual file on disk contains object code major + minor version

The real name is the actual file on disk that contains the compiled library code. It uses the naming format:

libname.so.major-id.minor-id

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
📌 Key Fact: The real name is a regular file — not a symbolic link. It physically holds all the compiled machine code for the library modules.

2. The Soname (libname.so.major)
symbolic link embedded in executable runtime lookup major version only

The soname (shared object name) has only the major version number — it drops the minor version. Format:

libname.so.major-id

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:

📌 Important: The soname is embedded inside the executable binary at link time using -Wl,-soname,libdemo.so.1. You can inspect it later with readelf -d prog | grep NEEDED.

3. The Linker Name (libname.so)
used at compile/link time no version number symbolic link -ldemo resolves here

The linker name is the simplest — it has no version numbers at all. Format:

libname.so

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:

📌 Note: If you want to link against an older major version of a library, you cannot use the linker name (it always points to the latest). You must specify the soname or real name directly in your link command.

4. Summary: All Three Names Compared
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):

gcc -ldemo

build command
libdemo.so

linker name (symlink)
libdemo.so.1

soname embedded in ELF

At Runtime (./prog):

./prog runs

dynamic linker starts
reads libdemo.so.1

soname from ELF
libdemo.so.1.0.2

actual file loaded

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

5. Coding Examples

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

Q1: What are the three types of names associated with a shared library on Linux, and what is the purpose of each?

The three names are: (1) Real name — the actual file containing compiled code, format 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.
Q2: What is the difference between a major version change and a minor version change in a shared library?

A major version change means the library has an incompatible API/ABI change — existing programs cannot use the new major version without recompilation and possibly code changes. A minor version change means a compatible update (bug fixes, new functions added) — existing programs automatically benefit without recompilation.
Q3: Where does the soname get embedded, and how can you inspect it?

The soname is embedded inside the ELF executable binary at link time by the linker. You can inspect it using readelf -d <binary> | grep NEEDED — this shows all the sonames the binary depends on.
Q4: Why is the linker name preferred to point to the soname rather than the real name?

If the linker name points to the soname, then when the soname is updated (e.g., to point to a newer minor version), the linker name automatically reflects that change too. This way, the soname is the single authoritative pointer to the current version.
Q5: How can you link a program against an older major version of a shared library?

You cannot use the linker name (it always points to the latest version). You must explicitly specify the soname or real name of the older version in the link command, e.g., gcc -o prog prog.c ./libdemo.so.1 or gcc -o prog prog.c -L. -l:libdemo.so.1.0.1.
Q6: What type of file is the real name, and what types are the soname and linker name?

The real name is a regular file containing the actual compiled library code. The soname and linker name are both symbolic links (symlinks). The soname symlinks to the real name; the linker name symlinks to the soname.
Q7: What happens at runtime when two major versions of the same library are installed?

They coexist without conflict because they have different sonames (e.g., 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.
Q8: Can a minor version identifier be a string instead of a number?

Yes — technically the minor version can be any string. But by convention it is a number, or two dot-separated numbers like 1.0.1 (minor=0, patch=1). Most well-maintained libraries follow this convention.
Q9: What command-line flag embeds the soname into a shared library file?

The -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.o
Q10: What is the role of ldconfig in managing shared library names?

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

📖 Chapter 41 — Shared Libraries Series
Continue learning with hands-on examples

Next: Creating a Shared Library → Part 3: Installing Shared Libraries

Leave a Reply

Your email address will not be published. Required fields are marked *