Follow this link https://github.com/slavaim/linux-notes/blob/master/dynamic-linking.md where I used GDB to show how dynamic linking on first function invocation is implemented in Linux.
(gdb) bt
#0 strcmp () at ../sysdeps/x86_64/multiarch/../strcmp.S:142
#1 0x00007ffff7deb1d4 in _dl_name_match_p (name=0x7ffff7bd83fe "libc.so.6", map=<optimised out>) at dl-misc.c:295
#2 0x00007ffff7de402f in do_lookup_x (new_hash=new_hash@entry=2090629905, old_hash=old_hash@entry=0x7fffffffdcb0,
result=result@entry=0x7fffffffdcc0, scope=<optimised out>, i=<optimised out>, i@entry=0, flags=flags@entry=1, skip=skip@entry=0x0,
undef_map=undef_map@entry=0x7ffff7ff9520) at dl-lookup.c:462
#3 0x00007ffff7de4961 in _dl_lookup_symbol_x (undef_name=0x7ffff7bd83f9 "puts", undef_map=0x7ffff7ff9520, ref=ref@entry=0x7fffffffdd78,
symbol_scope=0x7ffff7ff9878, version=0x7ffff7fcf030, type_class=type_class@entry=1, flags=1, skip_map=skip_map@entry=0x0)
at dl-lookup.c:737
#4 0x00007ffff7de9527 in _dl_fixup (l=<optimised out>, reloc_arg=<optimised out>) at ../elf/dl-runtime.c:111
#5 0x00007ffff7df04d5 in _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:45
#6 0x00007ffff7bd86c5 in foo () from /work/test/1/shared.o
#7 0x00000000004006f5 in main () at test.c:8