Ког­да прог­рамма в Linux вызыва­ет printf , sleep или любую дру­гую фун­кцию из динами­чес­кой биб­лиоте­ки, ее реаль­ный адрес заранее неиз­вестен из‑за ASLR. Тем не менее вызов каким‑то обра­зом сра­баты­вает. В этой статье мы шаг за шагом раз­берем, как работа­ют механиз­мы PLT, GOT и релока­ции, прос­ледим про­цесс раз­решения адре­сов с помощью objdump , readelf и GDB, а так­же уви­дим вжи­вую, что про­исхо­дит при пер­вом и пос­леду­ющих вызовах биб­лиотеч­ной фун­кции. В момент запус­ка прог­раммы в Linux ядро заг­ружа­ет ее в память, а динами­чес­кий ком­понов­щик под­гру­жает все необ­ходимые биб­лиоте­ки. Механизм, который мы будем раз­бирать, работа­ет оди­нако­во для любой динами­чес­кой биб­лиоте­ки, но в качес­тве при­мера мы возь­мем стан­дар­тную биб­лиоте­ку язы­ка C libc. so