Keyboard Shortcuts

Ctrl+K
Open search
Esc
Close search / dialog
↑
Back to top

The Dynamic Section

20 minadvancedModule 7: Dynamic LinkingContinues from dynamic-relocations

Why This Matters

When ld.so loads your program, how does it know which shared libraries you need? Where is the symbol table? Where are the relocations? The answer is the .dynamic section — a table of key-value pairs that tells the dynamic linker everything it needs to know.

The .dynamic section is the "instruction manual" that ld.so reads to set up your program's runtime environment.

A Simple Model

Think of .dynamic as a configuration file embedded in the ELF binary. Each entry is a tag-value pair:

The Actual Detail

Each dynamic entry is an Elf64_Dyn structure:

# Elf64_Dyn structure (16 bytes):
#   d_tag  (Elf64_Sxword)  What this entry describes
#   d_un   (union)         Value: either d_val (integer) or d_ptr (address)

Key tags:

TagValuePurpose
DT_NEEDED1Shared library dependency (offset into DT_STRTAB)
DT_SYMTAB6Address of .dynsym section
DT_STRTAB5Address of .dynstr section
DT_RELA7Address of .rela.dyn section
DT_RELASZ8Size of .rela.dyn in bytes
DT_JMPREL23Address of .rela.plt (PLT relocations)
DT_INIT12Initialization function address
DT_FINI13Finalization function address
DT_INIT_ARRAY25Array of init functions
DT_NEEDED1Each occurrence = one library dependency

A Real Example

$ readelf -d /bin/ls

Dynamic section at offset 0x3ba0 contains 30 entries:
  Tag        Type                 Name/Value
 0x0000000000000001 (NEEDED)     Shared library: [libc.so.6]
 0x000000000000000c (INIT)       0x3000
 0x000000000000000d (FINI)       0x5c1c
 0x0000000000000019 (INIT_ARRAY) 0x3be8
 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
 0x000000000000001a (FINI_ARRAY) 0x3bf0
 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
 0x0000000000000005 (STRTAB)     0x2288
 0x0000000000000006 (SYMTAB)     0x1a80
 0x000000000000000a (STRSZ)      568 (bytes)
 0x000000000000000b (SYMENT)     24 (bytes)
 0x0000000000000015 (PLTREL)     RELA
 0x0000000000000002 (PLTGOT)     0x3fe8
 0x0000000000000017 (JMPREL)     0x2918
 0x0000000000000007 (RELA)       0x27e0
 0x0000000000000008 (RELASZ)     312 (bytes)
 0x0000000000000009 (RELAENT)    24 (bytes)

The DT_NEEDED entries tell you exactly which libraries are required:

A complex program might show dozens of DT_NEEDED entries for different libraries.

Try It

# See the dynamic section of any ELF
readelf -d /bin/ls

# Count library dependencies
readelf -d /bin/ls | grep NEEDED | wc -l

# See what a typical program links against
readelf -d /usr/bin/python3 | grep NEEDED

# Compare: static vs dynamic binary
gcc -o dynamic hello.c
gcc -static -o static hello.c
readelf -d dynamic    # has .dynamic section
readelf -d static     # no .dynamic section (or empty)

Check Your Understanding

What is the purpose of DT_NEEDED entries in the .dynamic section?

Apply It

If you see a DT_NEEDED entry for "libfoo.so.3" but the library is installed as "libfoo.so.4", what will happen?

Connect

The .dynamic section lists library dependencies. But how do shared libraries themselves work — how are they built, versioned, and found at runtime? That's the next concept.

← Swipe to navigate →