Shared Libraries (Shared Objects)

Problems With Static Libraries

  • Only origanizational measure

    • ⟶ Copy of the code exists in every executable that links against the library

    • ⟶ Size of executable larger than necessary

    • Convenience operation: linker can look into an archive, and pick things out accordingly

  • Maintainability

    • A fix in the library requires relinking all users

    • ⟶ no central update of code

And Dynamic Libraries?

C Library is always linked dynamically for those reasons

  • What does an executable need?

    $ readelf --dynamic hello-first
    Dynamic section at offset 0x2e20 contains 24 entries:
      Tag        Type                         Name/Value
     0x0000000000000001 (NEEDED)             Shared library: []
  • Where would be found once I ran the program?

    $ ldd hello-first (0x00007fffe9fa7000) => /lib64/ (0x00007f75ca289000)
       /lib64/ (0x00007f75ca46d000)


  • Loader composes address space

  • Finds shared libraries that the executable depends on

  • Loads them into process’s memory/address space

  • ⟶ at different positions

    • Different executables depend on different libraries

    • Security: what if an attacker knew the absolute positions of executable code?


Building A Shared Library: Position Independent Code (PIC)

  • Shared libraries are not archives

  • Linkedgcc

    $ gcc -shared -o hello.o hello-flexible.o

But … 🤨

$ gcc -shared -o hello.o hello-flexible.o
/usr/bin/ld: hello.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: hello-flexible.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
collect2: error: ld returned 1 exit status
  • Code needs to be prepared to be loaded at varying positions

  • Position independent code (PIC)

  • hello.o and hello-flexible.o require special treatment to go into a shared library

    $ gcc -fPIC -c -o hello.o hello.c
    $ gcc -fPIC -c -o hello-flexible.o hello-flexible.c
  • And finally …

    $ gcc -shared -o hello.o hello-flexible.o

Linking Executables Against Shared Libraries

This is relatively easy, as opposed to building shared libraries …

$ gcc -o hello-first hello-first.o

And Build Dependencies?

Graph and Makefile basically unchanged …

digraph foo {
   "hello.o" -> "hello.c";
   "hello-flexible.o" -> "hello-flexible.c";
   "" -> "hello.o";
   "" -> "hello-flexible.o";
   "hello-first.o" -> "hello-first.c";
   "hello-second.o" -> "hello-second.c";
   "hello-first" -> "hello-first.o";
   "hello-first" -> "";
   "hello-second" -> "hello-second.o";
   "hello-second" -> "";
   "all" -> "hello-first";
   "all" -> "hello-second";
.PHONY: all
all: hello-first hello-second

hello.o: hello.c
	gcc -fPIC -c -o hello.o hello.c

hello-flexible.o: hello-flexible.c
	gcc -fPIC  -c -o hello-flexible.o hello-flexible.c hello.o hello-flexible.o
	gcc -shared -o hello.o hello-flexible.o 

hello-first.o: hello-first.c
	gcc -c -o hello-first.o hello-first.c

hello-second.o: hello-second.c
	gcc -c -o hello-second.o hello-second.c 

hello-first: hello-first.o
	gcc -o hello-first hello-first.o

hello-second: hello-second.o
	gcc -o hello-second hello-second.o

And Runtime Dependencies?

  • Executable is not self-contained anymore. It needs

    $ readelf --dynamic hello-first
     Tag        Type                         Name/Value
    0x0000000000000001 (NEEDED)             Shared library: []
    0x0000000000000001 (NEEDED)             Shared library: []
  • Who has and

    $ readelf --dynamic
    Tag        Type                         Name/Value
    0x0000000000000001 (NEEDED)             Shared library: []
  • ⟶ Runtime dependencies

    digraph foo {
    "hello-first" -> "";
    "hello-first" -> "";
    "" -> "";

And Starting An Executable Having External Dependencies?

The loader

  • Reads the executable (an ELF file)

  • Determines list of dependencies (shared libraries)

  • Searches for dependencies

  • Places them into the address space

  • Applies indirections ⟶ relocations


This Is Not Simple: Library Search Path

$ ./hello-first
./hello-first: error while loading shared libraries: cannot open shared object file: No such file or directory
  • Shared library search fails

  • Loader does not look in the current working directory (for security!)

  • LD_LIBRARY_PATH environment variable

$ ./hello-first
Hello World

Summary: Static Versus Dynamic Libraries




Static library

  • Easy to maintain

  • Executable do not have external dependencies

  • Versioning is not a problem

  • No single-file bug fix updates

  • Needs more disk space and memory

Shared library

  • Single-file bug fix updates

  • Saves disk space and memory

  • Cool in production

  • Maintenance nightmare during development

⟶ in larger code bases

  • Build static libraries during development

  • Switch to shared libraries for release