Great links so far! What I'm going to say is all Linux specific, but here we go. Object files (.o) created by the compiler, executable files created by the linker, and shared libraries (.so) are all ELF files. They all have sections that can be loaded into memory, with different permissions (usually read/write and read/execute), and may contain unresolved relocations and unresolved symbols ("please put the address of this here once you know it"). These are values which must be filled in somehow before the code is actually executable. For instance, a hello world program might have an unresolved external reference to the function "printf" or "puts" (try "nm program" to see). One object file might reference a global variable declared in another file, whose address is not known. Actually, object files have a lot of addresses which are not known because they all have a base address of zero. The linker's job is to put them all together into one program, such that there aren't any overlapping regions. Only at this point is the actual address of a function decided upon and thus any relocations that refer to the function may be resolved.

There's a lot of symmetry between these systems. The linker takes object files and resolves many (but not all) relocations to produce executables and libraries. The loader chooses an actual base address for a library (which can otherwise be loaded anywhere) and resolves all remaining relocations. So a statically linked executable, with all of its code inside the same ELF and all of its relocations already known, does not need a loader at all. But a normal executable does in order to handle its shared libraries. [It is also possible to create a position-independent executable, which acts much like a library in that its selection of a base address can be deferred until runtime. Like I said, there's a lot of symmetry here.]

The best part? The loader itself is an ELF file, statically linked of course, which simply knows how to open other ELF files and fix their relocations.

tl;dr the linker resolves relocations at link-time, and unless you made a static executable, there will be some relocations left which are resolved by the loader (or "dynamic linker") at runtime.

[edit] If you want to see more, try running "readelf -Wa program". [/edit]