Class 15: Linking To this point in the class, our view of programs has been of single source files that we compile and run on the processor. In fact, programs are built by a process known as linking, which collects and combines various pieces of code into a single file that can be copied (loaded) into memory and executed. Todays topics: 1. Static linking at compile time 2. Loading 2. Dynamic linking at load time 3. Dynamic linking at run time ***************** 1. Static linking ***************** Introduce simple example program in code/link/static driver.c: #include #include "kernels.h" #define X 2 #define Y 3 int debug = 1; int main() { int sum = add(X, Y); return 0; } kernels.c: #include extern int debug; int add(int x, int y) { int sum=x+y; if (debug) printf("%d+%d=%d\n", x, y, sum); return sum; } * Explain how program is compiled and linked and then executed * gcc is actually a "compiler driver" * Key idea: separate compilation % gcc -c driver.c % gcc -c kernels.c % gcc -o driver driver.o kernels.o % ./driver or % gcc -o driver driver.c kernels.c % ./driver Draw figure: driver.c kernels.c | | | | translators translators (cpp, cc1, as) (cpp,cc1,as) | | | | driver.o kernels.o Relocatable object file | | | | ----- Linker (ld) ---- | | driver Executable object file * Take a tour of disassembled kernels.o, driver.o, and driver. Initially, compiler puts placeholders for refs to functions and globals Linker fills these in later using relocation entries in each relocatable object file * Question: We've seen an example where one object file defines a global and the other uses it. What happens if two object modules define the same global variable? Strong symbols: Functions and initialized global variables Weak symbols: Uninitialized global variables Rule 1: Multiple strong symbols not allowed Rule 2: Given 1 strong and 1 or more weak sym, choose strong sym Rule 3: Given multiple weak symbols, choose any of them. foobar1: two strong symbols (procs) foobar2: two strong symbols (variables) foobar3: one weak and one strong symbol foobar4: two weak symbols (can skip this one) foobar5: insidious runtime error ********** 2. Loading ********** * Loading handled by system function called execve (more later) * Show picture of memory and how code and data are copied to it at load time ------------------------------ kernel memory (top 1/4) stack shared libraries heap data (uninit r/w data) .bss data (init r/w data) .data code (r/o code) .text <-- 0x4003f0 ------------------------------ ******************************* 3. Dynamic Linking at load time ******************************* * Question: How can we call printf() when it is nowhere to be found in the driver executable? Answer: Dynamic linking of shared libraries * Take a tour of code in code/link/dynamic-lt ******************************* 4. Dynamic Linking at run time ******************************* * Take a tour of code in code/link/dynamic-rt **************************** Case study (time permitting) *************************** * Library interpositioning using linking * Tour of code in code/link/interpositioning