Tuesday, February 1, 2011


Most modern programs are dynamically linked. When a dynamically linked application is loaded by the operating system, it must locate and load the dynamic libraries it needs for execution. On linux, that job is handled by ld-linux.so.2. You can see the libraries used by a given application with the ldd command:

$ ldd `which ls`
linux-gate.so.1 => (0xb7fff000)
librt.so.1 => /lib/librt.so.1 (0x00b98000)
libacl.so.1 => /lib/libacl.so.1 (0x00769000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00642000)
libc.so.6 => /lib/libc.so.6 (0x007b2000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00920000)
/lib/ld-linux.so.2 (0x00795000)
libattr.so.1 => /lib/libattr.so.1 (0x00762000)
libdl.so.2 => /lib/libdl.so.2 (0x0091a000)
libsepol.so.1 => /lib/libsepol.so.1 (0x0065b000)

When ls is loaded, the OS passes control to ld-linux.so.2 instead of normal entry point of the application. ld-linux.so.2 searches for and loads the unresolved libraries, and then it passes control to the application starting point.

The ld-linux.so.2 man page a high-level overview of the dynamic linker. It is the runtime component for the linker (ld) which locates and loads into memory the dynamic libraries used by the applicaiton. Normally the dynamic linker is implicitly specified during the link. The ELF specification the functionality for dynamic linking. GCC includes a special ELF program header called INTERP, which has a p_type of PT_INTERP. This header specifies the path to the interpreter. You can examine the program headers of a given program with the readelf command:

$ readelf -l a.out

Elf file type is EXEC (Executable file)
Entry point 0x8048310
There are 9 program headers, starting at offset 52

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x004cc 0x004cc R E 0x1000
LOAD 0x000f0c 0x08049f0c 0x08049f0c 0x0010c 0x00110 RW 0x1000
. . .

The ELF Specification requires that if a PT_INTERP section is present, the OS must create a process image of the of the interpreter's file segments, instead of the application's. Control is then past to the interpreter, which is responisble for loading the dynamic libraries. The spec offers some amount of flexiblity in how control may be given. For x86/Linux, the argument passed to the dynamic loader is a pointer to an mmap'd section.

No comments:

Post a Comment