Loading required package: exams
Static vs Dynamic Linking
One morning at Datadog, a client cat from a small startup called Panda the cat bear called for help.
The datadog service stopped logging data after they updated their servers.
Nini was calm as always: “This sounds like a linking problem. Let’s investigate.”
Niko: “A LinkedIn problem?””
“No, Niko. Linking is how we combine your program with libraries.
Sometimes the library code is copied into the program itself,
sometimes the program looks for the library later when it runs.”
The client added:
> “We just compiled our tool lz4cat
, but it fails to run. It says it cannot find liblz4.so!”
Your task today is to play the role of the engineer debugging the client’s problem.
You will build lz4cat
in three different ways — static, dynamic, and dynamic with RPATH
, on the Alpine Linux distribution. lz4cat
uses the lz4 library to do the decompression and output the content to stdout
.
By the end of this lab, you should be able to answer:
- What happens at build time vs run time?
- Why do some binaries run without extra settings, while others need LD_LIBRARY_PATH
?
- How do static and dynamic linking affect size and memory use?
You do not need to edit code in this lab. We will offer you a Makefile, create a sample compressed file for you to test the decompression. Just run the steps and answer the quizzes. Download the LZ4 compression library, build the library, and install it to Search for the following variables in the Makefile: Create a sample compressed file: Verify it doesn’t depend on any other library: The dynamic binary can be compiled, but it fails to start until the loader can find The RPATH hardcodes Q1. Which environment variable is read at build time by the linker to find Q2. Which environment variable is read at run time by the dynamic loader to find Q3. Which one hardcode the library path into the binary, so we don’t depend on any environment variable at runtime? Q4. Your dynamic binary failed before you exported Q5. Assume a library (a) Static linking — what is the total disk footprint? (b) Dynamic linking — what is the total disk footprint? Q6. Same scenario, but now 50 processes of A and 50 processes of B run concurrently. Which has smaller RAM use for Q7. If two different statically linked executables contain byte-identical copies of In the lecture, we talk about how shared libraries can amortize memory consumption because multiple processes can map the same Q12. According to article 2, if a library is only used by one program on the entire machine. It is more cost-effective to use: Q13. A C program compiled on Ubuntu 24.04 and linked only to Q14. You’re the developer of a single commandline tool 1. Hands-On
./setup.sh
to install LZ4 into the directory /os
.lz4cat
and run it.lz4cat
, watch it fail at run time, then fix it with LD_LIBRARY_PATH
.lz4cat
that runs without environment variables.ldd
, readelf -d
).Setup
/os
../setup.sh
-lfoo
to libfoo.a
/ libfoo.so
. No effect at run time..so
when the program starts. Ignored by static binaries.-Wl,-rpath,<dir>
) — A path baked into the ELF at build time that the loader uses at run time (no env vars needed).make sample
Static
make build_static
, then make run_static
ldd ./b/lz4cat_static
Dynamic
make build_dyn
, then make run_dyn1
, make run_dyn2
.liblz4.so
(you fix this with LD_LIBRARY_PATH
)RPATH
make build_dyn_rpath
, then make run_rpath
/os/lib
into the ELF so it runs with no env var.make inspect
(see sizes, ldd
, readelf -d
)Concept Check
-lXXX
library? .so
files? LD_LIBRARY_PATH
. What failed? libX
size = 3 MiB (code),. Ignore data and ASLR effects for this exercise. Two different executables A and B: 1) Each program’s own code = 1 MiB. 2) Each runs 1 process on the same machine. 3) Both use libX
.libX
code pages (text)? libX
’s code, the kernel will naturally share the same memory pages across the two executables. 3. Readings
.so
and share text segments. However, what if the library is very niche, and not many processes need it? These articles give us a different perspective to consider.LD_PRELOAD
: link 3 (Other fun things you can do)libc
will run on Ubuntu 18.04, because both Ubuntu 24.04 and 18.04 are installed with libc
. fzf
. On your Github repo, what’s the safest way to ship your program so it can run on multiple architectures? LD_PRELOAD
?