How linker resolves the symbol in assembly code

Assuming ELF file format, the assembler will generate an undefined symbol reference in the object file. This'll look like this:

Symbol table '.symtab' contains 11 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS test.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    3
     4: 00000000     0 SECTION LOCAL  DEFAULT    4
     5: 00000000     0 SECTION LOCAL  DEFAULT    5
     6: 00000000     0 SECTION LOCAL  DEFAULT    6
     7: 00000000     0 SECTION LOCAL  DEFAULT    7
     8: 00000000    52 FUNC    GLOBAL DEFAULT    1 main
     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
    10: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND exit

It'll also create a relocation entry to point to the part of the code image that needs to be updated by the linker with the correct address. It'll look like this:

$ readelf -r test.o

Relocation section '.rel.text' at offset 0x358 contains 3 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0000001f  00000501 R_386_32          00000000   .rodata
00000024  00000902 R_386_PC32        00000000   printf
00000030  00000a02 R_386_PC32        00000000   exit

The linker's job is then to walk through the relocation table fixing up the code image with the final symbol addresses.

There's an excellent book, but I can't find the details right now (and it's out of print). However, this looks like it may be useful: http://www.linuxjournal.com/article/6463