Advanced Features of Shared Libraries

 

Chapter 42: Advanced Features of Shared Libraries
The Linux Programming Interface — Deep Dive Tutorial Series
Dynamic Loading · Symbol Visibility · Versioning · Initialization · Preloading · LD_DEBUG
10
Tutorial Files
25+
Code Examples
40+
Interview Q&A
6
Major Topics

What You Will Learn

Chapter 42 of TLPI builds on the shared library fundamentals from Chapter 41 and covers advanced, production-level features. You will learn how Linux programs can load shared libraries at runtime without recompiling, how to precisely control which symbols a library exposes, how to maintain backward compatibility using symbol versioning, how to run setup/teardown code automatically when a library loads, how to override library functions for testing, and how to debug the dynamic linker itself.

These topics are essential for writing plug-in architectures, building robust shared libraries, and debugging complex Linux applications. Interview panels at embedded and systems companies frequently test this material.

Key Concepts in This Chapter

dlopen() dlsym() dlclose() dlerror() dladdr() RTLD_LAZY RTLD_NOW RTLD_GLOBAL RTLD_LOCAL Symbol Visibility __attribute__((visibility)) Version Scripts (.map) Symbol Versioning .symver directive constructor attribute destructor attribute LD_PRELOAD LD_DEBUG -ldl flag –export-dynamic

Tutorial Files

142.1 — Dynamically Loaded Libraries: Introduction & dlopen API

Understand what dynamically loaded libraries are, why they matter, the four core API functions, and how to link against libdl.

Dynamic Loading Concept dlopen API Overview -ldl Linking Plug-in Architecture
242.1.1 — dlopen(): Opening a Shared Library & Flags

Deep dive into dlopen() — all flags explained (RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND), reference counting, and dependency loading.

dlopen() Signature RTLD_LAZY vs RTLD_NOW RTLD_GLOBAL / LOCAL Reference Counting Dependency Tree
342.1.2 & 42.1.3 — dlerror() and dlsym()

Error handling with dlerror(), obtaining function/variable addresses with dlsym(), correct function pointer casting, RTLD_DEFAULT and RTLD_NEXT pseudohandles.

dlerror() dlsym() Function Pointer Cast RTLD_DEFAULT RTLD_NEXT Variable Access
442.1.4–42.1.6 — dlclose(), dladdr() & –export-dynamic

Closing libraries with dlclose(), inspecting symbol addresses with dladdr(), and making main program symbols available to dynamically loaded libraries using –export-dynamic. Full working dynload example.

dlclose() dladdr() Dl_info struct –export-dynamic Complete Example
542.2 — Controlling Symbol Visibility

Why symbol visibility matters, static keyword, GCC visibility attribute (hidden/default), and the three problems that uncontrolled visibility causes.

ABI Design static keyword visibility(“hidden”) Symbol Interposition Dynamic Symbol Table
642.3.1 — Linker Version Scripts for Symbol Visibility

Writing .map version scripts to precisely control which symbols are exported, global/local keywords, wildcard patterns, anonymous version tags, and readelf verification.

Version Script Syntax global / local Wildcard Patterns –version-script readelf –syms
742.3.2 — Symbol Versioning

Export multiple versions of the same function from one shared library. .symver assembler directives, @ vs @@, version tag dependencies, backward compatibility without major version bumps.

.symver directive @ vs @@ VER_1 / VER_2 nodes Backward Compatibility objdump -t
842.4 — Initialization and Finalization Functions

Automatically execute code when a library loads/unloads using GCC constructor and destructor attributes, multiple init/fini functions, and the older _init()/_fini() approach.

constructor attribute destructor attribute _init() / _fini() atexit() in libraries Multiple Functions
942.5 — Preloading Shared Libraries (LD_PRELOAD)

Override any library function at runtime using LD_PRELOAD. Per-process vs system-wide preloading, security restrictions for setuid programs, practical testing use cases.

LD_PRELOAD Function Override /etc/ld.so.preload Security Restrictions malloc() override
1042.6 — Monitoring the Dynamic Linker (LD_DEBUG)

Use LD_DEBUG to trace library searches, symbol resolution, relocations, and version dependencies. All keyword options explained with real output examples.

LD_DEBUG keywords libs / symbols / bindings LD_DEBUG_OUTPUT Process ID tracing setuid restriction

Ready to Master Shared Libraries?

Start from file 1 and work through each topic in order. Each file builds on the previous one.

Start Learning → EmbeddedPathashala.com

Leave a Reply

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