You can find how a linker works in any decent book on system programming.
Here is a nice simple introduction, but you won't see much detail:
http://en.wikipedia.org/wiki/Linker_(computing)[
^].
Main idea of behind a traditional linker is
separate compilation
. A separate units of code are compiled separately into
object files (
)[
^]. A lib file can be considered simple as a collection of the object files.
We're coming to the essence of the problem of separate compilation. The problem is: when a set of object files are bound together in a single executable file, the machine codes are put is a single
address space
. The tricky part is: when an object file is created, there is no information about of the addresses relative to other units (separate is separate: there is no information of other units). There is no information of the entry points of functions in other modules, they are presented in the form of
symbolic names
. The task of the linker is to resolve all relationships between symbolic names of different modules, arrange them in a single address space and
translate
all the addresses by some shifts calculated bases on individual positions of each unit in united address space of the resulting executable file.
In should be noted, that in most (almost all) platforms is is done separately for data and code address spaces and virtual memory is can be used, which is however transparent for the linker. There are several different memory models in different platforms. Dominating model in modern system is so called flat memory model, see
http://en.wikipedia.org/wiki/Flat_memory_model[
^].
—SA